 Hey everybody, this is Brian. Welcome to the, what are we on here? 135th, this is a continuation. This is the high-performance TCP server design part 4. I'm showing you that there's part 3 in case you're just now stumbling upon this video. You know that there are three preceding videos to this. And if you're just starting in Qt, I've done 130, well now 135 Qt tutorials. Before we begin, 41 years ago, something awesome happened. I was born. Yesterday's my birthday. I wanted to say thank you. I've had a huge, huge outpouring of people on my Facebook page wishing me happy birthday. And I just wanted to take a moment and say thank you very much. It was very humbling to hear from people all over the world, all different cultures and religions and beliefs and ways of life. And it's just, it's magical to me how something like programming really connects people. Other than that, I haven't posted in a few days, so quick update. I've been playing a lot of Dota 2, probably more than is actually healthy for me. And I started playing Counter-Strike Go, global offensive. Pretty fun games. You should try them. Anyways, let's just dive into this. I've wasted enough of your time. Today, we are going to take our high-performance TCP server and we are going to inherit the TCP classes that we made. Remember, we made the connections, connection and server. We're going to inherit those and make a very basic HTTP server. When I say very basic, I mean, it will send the headers, but it won't send the files. That's going to be in the next tutorial if we finish this one up. I may have to split it and do a few more because I've got quite a bit of programming to do here. So let's just go into File System and then Show Containing Folder. I'm never very good at this. There we go. All right, so we want to make a new folder. We're just going to call HTTP, a new document, HTTP PRI. There we go. Go back into Projects. All right, so we're going to actually change this a little bit. Now, when you do this, the little TCP folder should magically disappear. Oh, no, what have we done? But now we've got this beautiful little project include file. So the first thing we're going to do here is say cute. Oopsie, plus equal network. And we really don't need to do that. I just do it out of habit. Not now, kitty. Go away. As soon as I start typing this darn cat, I love him to death, but he just wants to be all over me and will do the pen path. Where is the dollar sign? I actually celebrated my birthday with my family yesterday because we all had the day off. So that's why I'm doing the tutorial today because everybody's gone doing their things. And I'm already all partied out. I've had, oh my gosh, my girlfriend made these amazing steaks. And if I eat one more steak, I'm just going to explode. I love steak. I'm like a steak junkie. All right, so what we've done here is we've gotten our little HTTP project include. We've added the network. We've set the include path to the current directory, the dependency path to the current directory. And we're including yet another PRI. And this is the TCP project include that we've been working on all these tutorials. So that shows you how you can kind of do that. So what we're really doing is we're segmenting off rather than keep adding and adding to this TCP folder. We can now segment it off and say, all right, we want to use this, but we want everything we're working on today to be in this little HTTP bucket. If that makes sense, we're going to make a few classes here. Add new class and let me look at my little notes here. Notes are always a good thing. Don't you think we're going to make a HTTP server? Make sure the path is correct. Sometimes some of the older versions of Qt Creator will play around with your path. I don't like it when people play around with my path. It makes me very upset. And we're going to make a HTTP connection. Now, following this design pattern here, let's see, just collapse that. You can see we have a server, connections and connection. But in here, we only have a server and connection. All we're going to do is inherit these two classes. We don't really care about the connections. We're going to let that do its magic under the hood. But we want to inherit and then override some of these functions here. So I'm going to try to get this all done in one video. But let me close some of these files. We do have a fair amount of programming in this little video. So I may have to chunk this up into two or maybe even three videos. So let's just start going away. Let's see, Qtabug, not now, Kitty, Daddy's busy, Daddy's very busy. Include, we're going to include tcpserver.h because we're going to inherit it. And we're going to include the HTTP connection. And we're going to inherit the TCP server, not to be confused with Qtcpserver. We're inheriting this class. And this class inherits the Qtcpserver. All right. So we've done that. Now we need to go into our sources and remember to change that as well. Otherwise, you're going to have build errors. Oh, my gosh, I'm not kidding. When I say if I eat one more bite of food, I'm just going to explode. I really just like my stomach's actually hurting. I'm like, now we're we're making a root and set root because a web server has what's called a root path or where it will begin looking for files. Because really, all it is is it's a generic file server. And it uses the HTTP protocol to transfer files back and forth, which is actually a very simple protocol. And we're going to add a rate in here. Rate is going to be the speed at which we transfer the files. Not going to do a whole lot with that. This tutorial that's coming in the next or maybe a couple now, depending on how fast I can do this one, what we're going to be doing in the future, just while I'm typing, we're going to be sending files at a specific speed. Because if you just, you know, open the socket and start sending the file, you're going to send as fast as it will go, which is going to consume that entire bandwidth. And it'll essentially, you know, deadlock other clients. So we want to really throttle that down. I mean, like when you've noticed, I think I've talked about this. I can't talk and type at the same time for some reason. When you go to a website and you go to download a file, even though you got like a four meg connection, you're only downloading it like 300 K or something like that. Well, that's actually the the actual web server. Well, why did I hit caps lock there? Cue it pointer. It's the web server throttling the connection. Sorry, I was trying to finish my train of thought here. I'm like trying to type, talk and look at my notes all the same time. And it's not going very well. OK, so we're going to flesh out this class a little bit here. We're going to have to actually, you know, do a little bit of this and jump into the connection and then come back. So let's just go. Whoopsie. Darn you. That's somewhat embarrassing. There we go. Someone sent me the keyboard command of that. And darn it, I keep forgetting. And now it's doing again. Here we go. I keep forgetting what it is, and it's actually kind of embarrassing that I keep forgetting it because people keep reminding me. But I guess that's what happens when you're older. You know, you just forget things all the time. Unless you ask my girlfriend, then I just intentionally forget things like taking out the trash or whatever she was just talking about. I wasn't really paying attention to her. I'm just kidding. OK, so I actually right off the bat, I do kind of see. Something we should do here. We're going to include Q core application just because I said so. All right, so we've got our little constructor here. We're going to say M route and we're going to set our value here. Yeah, Q core application, application, dirt path. So what we're really doing is we're saying the default route is going to be the same path as the application. It's big security risk. You really don't want to do that in production code, but I just want a value in there in case I forget to do it in a future tutorial, it'll be something. And we're going to set the default rate to 15 K. I think that's 15 K. Me 1024 by 15. Yeah, that's 15, 360. That's 15 K. So 15 kilobytes per second is what we're going to be sending files at. And then this is pretty easy, maybe. There we go. We're going to set the path here. And then we're going to do a little, you know, just defensive programming. Whoops, I want it or not. And basically what we're going to do is just remove the trailing backslash. And there's probably a more elegant way of doing this. I'm always amazed at some of the some of the messages I get of, dude, this one video, this one time, that one thing that you made. Yeah, you screwed up. It was a lot easier if you just do blah. And I'm like, oh, why didn't I think about that? It makes me feel kind of stupid. But at the same time, I really love the collaboration. So if you have no idea what I'm typing here, you should probably go back to introductory C++, but I'll explain it just in case. We're really just saying if the variable emroute, which is this path, ends in a slash or, you know, a other slash, we got to do double slashes because that's what's called an escape character. Then we're going to say root actually equals the path minus the last character. And then we're just going to say Q to bug. Like I said, I'm sure there's a much, much easier way of doing that. But while I'm old school, I just like doing things the hard way. Whoops, root set to I like throwing Q to bugs in there just because I can see what's going on under the hood. It makes me happy to see things going on under the hood. All right, so I don't want that. Yeah, so having a few days off, sitting around the house, playing video games, my brain has kind of turned to mush. So, you know, sorry, bear with me here. But you got to do that once in a while. I call it instead of a vacation, I call it a staycation because I stay at home. I love staying at home and playing video games and just, you know, Netflix and vegging out and doing whatever. My girlfriend, on the other hand, likes to travel the world. So I have to try to find a unique balance between, you know, goofing off and doing whatever versus, you know, flying to Paris, which I have to say, Paris was actually amazing. And I do want to go back, but I was really glad to get home and have my computer. All right, so so far, this class is pretty skimpy here. We just have, you know, a route. We have a rate and now the meat of the of the issue here, the incoming connection. Now I want to jump into this little guy here because I think we've talked about this before, the queue socket descriptor, or I'm sorry, the incoming connection, the queue and pointer, the descriptor. This is a little bit different depending on what version of Qt you're using. You notice I'm using Qt pointer. I've seen it as Q at 64, Q handle, Q pointer, and even as you end, so depending on what platform and what version of Qt you're using, that may be different. So I'm just going to put that in there. So if you download the code and you run it and none of the connections are actually connecting, it's like the client thinks that it's connected, but you don't see it happen in the program nine times out of 10. That's the problem. You got the wrong data type. They're all supposed to be essentially the same thing, but they're different. They're very, very different under the hood and Qt understands that they're different and that's why you have problems with that. And if you try to do like an incoming connection, Q into 64, an incoming connection, Q handle, you get all sorts of funky, weird compile errors. I haven't quite figured it out, but it really kind of messes with your head. So anyways, I just wanted you to be aware of that. It's a very big gotcha that I see a lot of people having problems with. I get probably, I want to say about 30 emails a month just at one question of, Hey, I'm working with a TCP server. I can't get an incoming connection. What am I doing wrong? That was embarrassing. Can't spell incoming. I'm going to say incoming HTTP connection because, you know, why not? I hear like this weird humming. I don't know what the deal is, but I hear it. My girlfriend got me a new wireless headset for my birthday, but it hasn't gotten here yet. So really psyched up about that. This headset, I love it. It's a Logitech G930, but once in a while, like, especially if somebody kicks up the microwave or something, it'll drop the connection and it drives me crazy because I don't know that it drops the connection. So I'll either be making a video or I'll be gaming and just suddenly I hear it go beep, beep, meaning it just reconnected. So then I have to figure out what did I say versus, you know, what they heard. Anyways, it's just annoying. So what we're doing in the incoming connection here is we're just literally making a new HTTP connection, which is an inherited version of the TCP connection or it will be as soon as we're done with it here. And then we're going to accept it very much like we did in the TCP server. Well, actually exactly like we did in the TCP server. We're going to say descriptor connection, boom. And to do, set rate and root. Wow, I cannot type. I actually had so much steak. I know some of your vegetarians and I'm trying not to gross you out, but I actually had so much steak. I felt like I ate a bowling ball. I'm not even joking. I mean, like I literally felt like I just ate an entire bowling ball and I love red meat. I don't know why I just do. All right, so we've got our server. We got a little bit of work we're gonna have to come back to, but that's kind of fleshed out. The connection on the other hand is gonna be a bit of work here. And there may be a few sections where I just blatantly copy and paste just to save time, but I will try not to do that because I know you guys really are masochistic and you like watching me type. So we're gonna include Q file because we are essentially making a file server. My, one of the presents that I got for my birthday. It's hilarious. I gotta find a picture of this. It was, it's a cat bed, but it's shaped like a hamburger. It just cracked me up because it looks like a cat burger. My cat won't go anywhere near it though. He's too smart for that. Q core application. I'm not sure if we need Q core application in here, but we'll do it anyways. Include, we're gonna override TCP connection or override inherit and then to do make a rate controller. Once again, when we transfer the file, we have to throttle that bandwidth. Otherwise we're gonna consume all of it and we're gonna deadlock everybody else. So let's just flesh this out super quick. Kind of curious what video games you guys are all about. They're playing, I've been playing defensive the ancients or Dota. And I'm very not good at it. I'm the opposite of good, which is weird because I'm usually pretty good at video games. I'm a very big computer guy and when I play video games, because as I'm programming, I can actually think under the hood what is this game doing? And I can figure out kind of, not cheating or hacking, but I can figure out, okay, well, it's got a random loot table that pretty much once a second or once a minute or once every 10 minutes response. If I come back at nine minutes, it'll be better loot, that sort of stuff. But this game is different. It's very much a team game. And sometimes your team is not good. In fact, sometimes your team just sucks. Let's put it that way. I had a very crappy team the other night. I wanted to like reach the monitor, just punch, throw everybody, you know. Yes, I said punch, throw, throw, punch. More like it. Hint and rate. I gotta quit hitting caps lock here. All right, so what we're doing is we're just making our little internal variables for this class. We're gonna have a file because we're sending a file. We're gonna have the route path and the rate, which we're gonna set and you guessed it up here. And then we're going to, and let me add this in here while I think about it. Really shouldn't need this, but I like to add it just in case I've seen some versions of Qt that kind of freak out a little bit if you don't do it. We're gonna call Qmap, Qstring. And we want Qstring. And what we're doing is we're just making a variable for the request header. HTTP protocol. Basically sends some information for a request and then you have to send some information and then the file and the information is just metadata that describes what you're sending. And we're gonna get a little bit into the, well, actually we're gonna get a lot into the protocol today, but you'll see. It'll become much clearer or it'll become much more confusing. I haven't decided which yet, but we'll get there. And then mimes because every file on your computer has what's called a MIME type. Am I pronouncing that right? M-I-M-E MIME. So like a .txt is a text file. That's its MIME type. A JPG is a JPEG file. That's its MIME type. It's just a description that says what type of data the file you expect is going to hold and what application would it be associated with. So that was really what we would do. And then we're gonna say to do make a rate controller. If you haven't figured that out by now, that's actually a pretty important part of this program. It's actually kind of the bread and butter of how this thing works, but we're not gonna have time to get to it today. We're just laying the foundation for that. Say void, process get. If you're wondering what get is, well, it's all mine. Get is a part of the HTTP protocol. You can do things like get input. Get is requesting a file. So we're gonna handle get requests. Put is when you wanna put a file. So if you wanna upload a file to the server, which is probably, I think it's probably outside of the scope of this tutorial, but we might add it, I'm not sure. Might not add it until many, many decades into the future. So we're gonna handle the request, void send file. That's pretty self-explanatory of what it's gonna do. And Q string, get MIME type. And we're gonna just, we're gonna call that path. All right, so very super short version of what we got going on here. Got our getters and setters. We've got some, well they're not true getters and setters. I know I'm gonna get hate mail for saying that, but we've got our Q maps. We're gonna have our request, our response, our MIME types. We're going to make a rate controller in the future. We're gonna process the get, handle the request, send a file, get to MIME type. Now we need to do public slots here. And I am actually going to just copy and paste because this is gonna take forever if I don't. Look at all that typing I just saved. And we'll go over them super quick. We've seen them before. Connected, disconnected, ready read. Bytes written if you probably guessed we're overwriting these. The space or the line here is to show that we're not overwriting these. These are actually unique to this class. And of course the error. So let's just start plugging away at this bad boy. Oops, I actually wanna go up here first. Damn you cursor. So I've been talking with a couple of you by a Facebook messenger. It's one of the easier ways to get a hold of me. One in particular, she'll know who she is. Excuse me. It's stuffy in here for some reason. I've been kind of getting into embedded hardware and stuff like that. I made my own saltwater battery. And she kind of turned me onto these. It's called a field programmable. Now that I'm on the spot, I've totally lost the name of it. Basically it's like the Arduino but instead of making, how can I describe this thing? It's a field programmable device. And I'm just babbling like an idiot because I can't think and do this at the same time. But with a normal microprocessor board like an Arduino, somebody's already made the circuit. And this is, I think it's a field programmable gateway, something, something. Maybe I'll look it up at the end of this tutorial. Anyways, you can design circuits in this thing using a special programming language which is very much like Java and C++. And it's really friggin' cool because you'll have like 84 pinouts and you can designate which one does which so you're not stuck with okay, I've only got three serial lines. You can say, no, I've got 80 serial lines because 80 serial lines, I need them all. Why you would need 80 serial lines? I'm not quite sure. But you know, it's just really neat that you can actually design this. And I found that a lot of companies will actually, they'll use these things for prototyping purposes. No matching function call for accept. Well, what have we done here? What do you mean? What have we done here? Oh, I know what we haven't done. We haven't inherited this thing yet. Inheritance 101, ladies and gentlemen, you must actually inherit. All right, let's do this. This should actually work much better now that we try to do this. Just gonna give it a quick build, make sure we don't have any stupid errors like that. We've got a lot of unused parameters, which is really not a big deal. I've seen some people that are like, oh, you've got warnings in your code. Unused variable is really not a warning. It's just the compiler being stupid. Okay, magic and copy and paste time. I'm gonna save us about 20 minutes of me babbling here. Boom, that just happened. All right, so what just happened, you ask? Well, the map, the qmap, the mime variable. Really all I've done is I've added the file extensions and then the mime type. So example, txt is text plane. Why do I have two txts in there? We'll fix that problem. Anyways, so like, htm is text html, htm is text html, javascript, rtfjpeg, gif, mpg, mistroka, qtwebm, you know, on and on and on and on. Now, the reason why I'm doing this is because Qt is a cross-platform language, meaning you may be downloading this on Linux, you may be downloading this on Mac, you may be downloading this on Windows, and every operating system handles this slightly differently. For example, Windows is in the registry, Linux, it's in a file somewhere, Mac, I'm dead certain it's in a file somewhere in Mac, but the problem is what file, what operating system? So if somebody else comes in, downloads this for Solaris or some embedded system, it may not have all that stuff. So we're just adding what I've called the default MIME types that you're probably going to encounter on a webpage and just throwing them in here real quick. Anything beyond that, you're gonna really either want to send an octet stream, which we'll get to later, or you'll want to actually look up in the registry or whatever file that's specific to your OS. But just so this thing works when you guys go out to go to use it, we're gonna just throw that in there. All right, so maybe it didn't save that much time because I had to stop and explain it all, and I could have probably explained it while I was typing it, but it's my birthday, so we're gonna just cut me some slack here. All right, so somebody asked from the last set of tutorials, why are you doing destroyed in the deconstructor? Why do you want to queue debug there? Because we're making objects dynamically, and I want to make sure that memory is cleaning up as we work. I don't want objects sitting out in memory. Anybody out there watch IT Crowd? If not, you gotta look it up. It's called IT Crowd. It is just hysterical. I thought it was on Netflix for a while, but it was a British show, and it's about a group of people, well, in IT, and it's just, words cannot describe it. I mean, you've got to go watch this. It is so funny. Unfortunately, it was only five seasons long, and then it got discontinued, but oh my God, what a five seasons that was. Anyway, so once in a while, you're here, let me make a reference to it where they're like, have you tried turning it off and on again? Because that was like their default answer to everything. It's a lot of funnier if you just go watch it, otherwise it just sounds like I'm a lunatic. All right, so pretty much the same thing as the other class. We're just gonna set the rate and the path. Somebody asked a question, or will ask the question, I should say, of why don't you just give it a pointer to the other class? Because I don't want to. I want loose coupling between classes. It's actually a design pattern is loose coupling between classes. You want the classes to be as independent as possible because you don't want them to rely on things that could potentially be broken later on in life. So for example, if I'm working on this class and Sally's working on another class, whoever Sally may be, damn you, Sally. Anyways, and she changes something that my code depends on. Now I've got to go through and figure it out and fix it. It's not fun, I've been there. All right, so process get. Process get. That is a whole lot of code that I've got to type out. Let's start doing it, I guess. The whole point of process get is to process the incoming connection. Whoopsie. All right, so we're gonna do a QBite array, EOH, which is short for end of header, EOH.append. And the end of the HTTP header is two new lines or carriage return line feed, carriage return line feed. That's how we know the difference between the header and the payload, as it's called. Typically they won't send a payload on a get, but they might if they have like a cookie or something, because remember, websites have cookies. Oh yeah, she could very easily build that into this program, but we're not there yet. We're still trying to process get, so. And request.value. Now remember, emrequest is, well, you guessed it, it's a Qmap. So we're gonna see if we've got a value called SVR underscore header, and if we have not, then we're just gonna have a blank variable. Otherwise, we're gonna get that. Because what might happen is you may have a header that's longer than your packet size. This day and age, I seriously doubt that, but it may happen. So you wanna keep appending that header until you get this end of header marker. So header, append, data. And all we're doing is just putting the variable back in the map. Now, this is where the magic happens. If header.contains, EOF, that marker we're looking for, then parse the header. Nice, right? Okay, cool. So, if we've got our end of header, then we're just gonna start parsing this bad boy. Whoopsie, cannot spell. Header, split. And we're gonna split this based off return line feed. So basically we're gonna read the lines out of this thing. Whoops, I cannot type, read my notes and thank all at the same time. All right. Sorry about that. I just wanna make sure I was in the right spot here. Reference to string list in here. Is that what's going on? I think that's what's going on. Should just be count. Okay, what is wrong with you? Maybe I misspelled string list. Yeah, I did, that's the problem. Okay. All right, let me get a quick drink of water here and you get to listen to it in all its glory. My throat gets really dry, which I don't know why because it's like 90 degrees and extremely humid for some reason. So we're just gonna split it by lines and then we're gonna read each line. We're gonna say Q string line at i, we're gonna get the current line. First line has three values, which is kind of a pain for us and they're separated by spaces. So it's HTTP path. Or actually is it, yeah, it's path version. I think that's right. It might be version path, but I'm pretty sure it's HTTP path in the version. All right, so Q string list, items. We're gonna split based off space. If we've got a count greater than equal one, then we're going to insert the method. Actually, that's what it is, sorry. And we're going to say, let's call this TTV method. We're going to add that in there. And we wanna actually do trimmed just because we wanna make sure there isn't any trailing space in there. They really shouldn't be because we're splitting it. I just wanna make sure that through the magic of copy and pasting speed, this process up a little bit here. So if we have more than two or two or more, gosh, I'm horrible at this, aren't I? All right, so this is a little bit different here. This is where we get the actual path. So we have to say, this is the actual relative file path. So really, it's not gonna be the full path of the file and this is where it gets a little bit tricky and this is where a lot of attacks on web servers actually happen. For example, it's going to send you a path of like, let's call it slash some file or actually some der slash some file.txt, right? That's all it's gonna send you. It's not gonna send you the full path. That's where your root path comes from. So they may actually send you a dot dot or a slash dot dot. So they try to go up in directories. I mean, they can go all the way up to your root directory, which is a big no, no, you don't want that. Cause then they can download, you know, your password files and things like that. Q URL from percent, encoding to Latin one. And all we're really gonna do is we're gonna load this because it's gonna come encoded. Like if there's a space here, there won't be a space. It'll be like, what is it? Percent 20a or something like that. I don't remember. It's just gonna be some weird encoding. So we're just gonna take that encoding out of there, right? And then we're gonna insert the actual path here. All right, now we're going to get our third item here. And I think we can just do this. We can just say, we don't want that. We want to, and we're gonna get the second item here. Remember it's a zero base. So you gotta go zero, one, two. In case you're wondering why it looks like that. All right, so let me double check here. Yeah, I did miss something. Let's just cut this out, cut, cut, cut. Want to make sure we're on the first line. That's what I was forgetting. That's why it looked kind of funny to me. There we go. That looks better. So if I equals zero, meaning we're the first iteration of this loop, then we're going to process that first line. And there's a lot going on there because it's method path version. Method will be get or put. Path will be the file path and then whatever HTTP version they're using for their protocol here. All right, all of the lines are key value pairs. And these are much easier. Well, I say much till we dive into this thing. So, oopsie, I knew I'd screw something up. Sorry about that. Want to make that available to that scope. We want to make sure it actually contains the little marker there. The key value pairs will be separated by that. Well, I screwed that up. All right, so we just want a warning and we're going to get some of those because, well, the protocol ends with two hard line returns. So we're probably going to get a few warnings here. But we just want to continue. And we could say if line is greater than, or if line is actually not empty. And let's actually do that. Let's actually do this right here. Ah, get up there. Make sure the line's not empty. That way we know something is kind of scurry where that requests some browsers are a little different, right? Just going to get the index of that. And then we're going to do some basic string parsing. This is like C++ 101. We did this back in Hello World and what's a variable kind of thing. I think my girlfriend's going to get home any minute now. We may have to do another tutorial here and pick up where we left off. All right, so we're just going to add those key value pairs in there. And in case you're wondering, it's going to be like, you can look it up online what the HTTP protocol is, but it's going to be like browser version, what languages they accept, what encoding they accept. I mean, it's actually quite a complex little protocol for what it is. So it's kind of interesting to see that. So if we can, let's see, we've done this, we've done that, now we got to go. And we could have put this all in one giant function, but I really don't like doing that because it makes it easier to break them apart. Keep it simple, stupid. Process get, we're just processing the header. And if we don't have the end of header marker, we just keep dumping into that variable right here until we have it. Once we have it, then we, you know, parse everything out into that Qmap. All right, so handle the request. Let's give this a good build. We did a lot of coding. I want to make sure there's no real little gotchas in there. Nope, nothing so far. All right, good. So we're going to handle the request. We're going to get the path that was in that first line, remember. There we go. Now, you could very easily use this as a parameter to this. You could say, you know, send it over right here to here. But I actually like keeping everything in that Qmap. So if later I want to go and I want to evaluate the request, I've got it in a nice little object called a Qmap and I can just reiterate over the key value pairs and see exactly what's going on under the hood and what blew up. I don't know if you can hear that bird in the background but it's driving me crazy. It's just chirp, chirp, chirp, chirp, chirp. We're going to strip out any directory jumps. That bird's like 20 years old. It's my girlfriend's. One of these days it's just going to have a heart attack and die. All right, so if they try to, you know, go up a directory, go up to the parent, we're just going to, you know, get that out of there, return a 404 not found. Whoops, we won't. So we're just going to take our root path and our file. So for example, our root would be like something mydir something slash something. And we're going to add that to slash file.jpg or whatever. Actually, let's just do test.jpg. That's basically what we're doing there. After we've removed the directory jumpings. Now the root file or the index file is called index.html. Some other servers call it index.html or index.php or asp or whatever you're doing. Basically, if it's a directory they're asking for, you check for this file and that's the file you'll send them. So missed a few things, didn't I hear? Queue file, endo, info, fi, file. Actually, let's call it actual file. That'll probably work a little bit better, right? Queue file, add array, response. And we're going to actually generate the response here. And this is where we're going to build the, you know, the 200 okay or the 404 not found. I know you've probably seen 404 not found. That means the file you're looking for was well not found. 200 okay, you've probably never seen because 200 okay means we found your file here it is. So you see the file, but you don't actually see the response. So anyways, it'll be pretty obvious what's going on here. So if it's a directory then do this. Otherwise, well actually I don't want to do that. So yeah, the thing I was babbling about is about the field programmable device. It's actually really wicked cool. You gotta go look those up. You would think that I would remember the acronym because I actually did read about it quite a bit today and I'm actually going to go buy one just to play around with. All right, queue string. All right, see my headphone just cut out. I heard it beep. So I wasn't really talking about much. So if my voice cut out, it was babbling on about that field programmable device. Oh my God, that bird is just going and going and going. I swear he's gonna give himself a heart attack. Let's call this F index. Very particular about my file names and I don't know why. If F index, nope. I'm very particular about it, but I also screwed it up. Sorry, my bad. There we go. It's that bird man, he's screwing me up. Simon, be quiet. Not only is the bird noisy, he's also deaf and just doesn't listen. So, well, he actually stopped. Maybe he died. I shouldn't say that. The bird eats fried chicken. I've never seen a bird eat another bird. It's kind of creepy. My girlfriend will feed him fried chicken and he loves it. It just really just creeps me out, man. So really all we're doing is we're saying if they requested directory, then we're going to set it to the default file. Sorry, kind of tripped over my own fingers there. So if they requested directory, set it to whatever they're asking for and an index file. Now we're going to check to see if that bad boy actually exists. It's got to exist and it's got to be a file. Pull up my notes here. Very simple to easy and understand logic of what's going on there. Now we just got to build out this response, if you will. Going to get the mime type of the file and then we're going to go queue debug. I should do file path. So we're going to send the file. Now I have to say in this tutorial we're not actually going to send the file. Bear with me here. Coming up in a future tutorial, we're just going to send basically the header. We're going to set the response code and I'm going to just copy and paste here. So I'm going to get a little tired of typing. Whoopsie. All right, so this is where we're going to actually make the protocol, the header, if you will, that we're going to send. And we're going to say new line. So that's our first line, which is just the version, the response number and the response text. Then we need to do content-type. And this is that mime type that I was talking about. We need to actually tell the browser, the client that's connecting to us, what type of file we're sending it so they know how to handle it. You think that they would just be handling that logic on their own, but no, they need a lot of hand-holding and it kind of bothers me that they do that, but whatever. We also need to tell them how long this file is so that they know how long it's going to take to download this sucker. And by doing this, I'm actually trying to save us a lot of typing in the near future when we actually send the file. All right, now, last but surely not least, we need to tell them, hey, we're going to close this connection because in HTTP protocol, it will actually hold that connection open so it doesn't have to reconnect and all that. And then we're going to add another blank line. There's that hard return, hard return the end of the header that you've seen before, right? So that is the basic HTTP header and we're just going to, through the magic of copy and paste here. And let's actually, we're doing this response so that later, we can actually go through and very quickly look up what sort of response we're sending and we're doing that for a specific reason which we'll cover in just a bit, just bear with me. And all we're going to do, we don't need this mime type or length because we don't have it. We're just going to say four or four not found and we're going to close the connection on you. Goodbye, have a nice day. Once I got, I need a drink. My throat's like super dry. Sorry if you can hear me swallowing. This microphone's like super sensitive to weird sounds. My cat made this weird squeaking noise the other day and it picked it up. I was like, what the frick? Now we're going to actually write the response out. Hoo, let's give this thing a good build just to make sure we haven't, oh, see. It's all fun and games until somebody screws something up here. All right, unresolved const binary operator. Well, that's a very long error message for you forgot your brackets there. There we go, that looks much better. So let's kind of jump back to the beginning because the rest of this is, you know, I don't want to say it's easy but it's definitely not near as much typing. It's just a lot of, you know, Q to bugs. We're setting our MIME types. We are, you know, just setting the root, setting the rate. We're processing the header, the get request and then we're going to handle the request. Now, notice we haven't done anything with these yet. That's coming up here and these little beautiful things which we're going to start fleshing out. So to do make a rate controller. The reason why I'm not sending the file in this tutorial is very simple. We don't have time. It's going to be like another two hours of me typing and I can't fit all that in one video. I'm really trying to hustle as it is. So all we're going to do is send the 200 or the 404 and then load it up in Siege just to make sure that it's actually processing the HTTP protocol correctly. So end pose. And what we're going to do in this little section is we're going to look up the MIME type based off the path and we're going to, just because I don't want to type that out, whoopsie. Double whoopsie, there we go. In case you're wondering, application octet stream is the default MIME type for web traffic. It just means we don't know what it is. It's just an octet stream. It's just a big blob of data. So Q string, mid and we're going to say pose plus one. We want to know that dot location plus one and then two lower. So basically we're just looking for the first period and then we're going to get everything behind that and call that the extension. Now there are little tricks you can do with like Q file and Q file info, but I just wanted to do it this way because I wanted to do it this way. So if our little Q map of MIME's contains that extension, notice how I did it two lower, two lower, I cannot type and talk, jeez. Now I'm actually kind of embarrassed that I can't, it's feel programmable, I'm not going to let that go, feel programmable gateway or something like that. I will find that out and I don't know why I'm being so absent minded today. Well actually I do, work kind of sucked today. I mean it sucks going in on your birthday but having a sucky day at work on your birthday is even worse so it's kind of like I just wanted to come home and chill. All right, now for the rest of these, pretty simple, connected. I'm just going to copy and paste that, disconnected. Ready, read. This is where we're going to make some magic happen here. Want to make sure we actually have a socket object. Now you could get that from get socket but I want to do the internal M socket variable. Q debong. What's a Q debong? Q debong sounds like when you throw your college roommates bong out the window or something. We're just going to read all, we're going to throw that in a process get. And remember that'll just keep looking for the end of header and if it can't find it, it just keeps adding to it until it finds it. So that could be a potential security flaw in this program already is they could just keep sending data and eventually crash the server. So want to maybe in the future modify that a little bit and let's flush some of these out super quick. Bites written. Bites written is not something that we normally work with. But we're going to work with it this time. Whoops, I was in the wrong window. Bite written is called once while you guessed it, the socket is actually written bytes. So once we've written bytes, the only time we're going to write bytes, I should say the first time we're going to write bytes, we're going to know that we are writing the header. Therefore, Q string code equal M response value. And we're going to get that code that we stored earlier, right? The 200 or the 404. So that way we know how to handle each one. So if we're sending a 404, we're just going to say msocket.close because we're going to close the connection and then return. However, if it was a 200, which it won't be for this tutorial because we're not implementing it, but we're just going to flush it out anyways. All right, so we're going to then send the file and you very well could put that this line right here. You could very well put that in send file and not have a parameter, but I just felt like doing it that way. We can easily see what's going on here. And then we'll handle that in the rate controller class. So let's not worry about that right now. And I'm going to just copy and paste some things just because they're very easy. They're just Q debug statements here. We're kind of on the home stretch and I just want to really get to this so we can go over what we've done. Now, we won't see any of this fire off in this tutorial because this is going to be part of the rate controller class that we're going to hook into. Once the file transfer is finished, if we did a 200, okay, then we would actually close the file and close the file socket, which none of that's going to trigger off in this tutorial. I'm just adding it as the groundwork for the next tutorial because it looks like we're going to finish this up on time. So let's give this a build. Oh, come on. Oh, yeah, yeah, you're not there, are you? And give it a good build. All right, so let's run this bad boy and we're not done. Grr. We're going to switch that out. Oh, we're going to take that out and we're going to say, everything else should just work, right? We'll start that. And now let's find my little handy. Now you see that Siege is reporting 404 not found and it's not going for a few seconds and then stopping. It's just going and going and going and going. You can see our connections are just hammering away over here and that's because we're actually returning the HTTP protocol. There it is right there in your window, the HTTP slash 1.1404 not found. So if we actually control Z out of there, whoops, not pucky, I did the wrong one. Let's run it again just because. There we go, now I'll stop at control C. You can see the just in that little second time we had 3,530 hits availability 100% meaning the server did not drop any of those connections. Transaction rate, about 1,000 transactions per second which is actually pretty speedy considering we're not really doing anything. Concurrency, successful failed. Notice how failed is zero because we are actually returning the protocol this time whereas before we weren't. So we had a bunch of failed. The longest transaction took three seconds. So that's actually an eternity in network time so we are really hammering this bad boy. So that's it for this tutorial. The next one we will actually cover the rate controller and then tentatively actually send a file and see this thing work in action. Whew, that was a lot of typing and whoops, you can see how our client count is now zero. So you can see how it's actually cleaning up, disconnected, removing, et cetera, et cetera. That's why you do all those Qtabugs and you can see it's the HTTP connections. Anyways, that's it for the source code for this and other tutorials. Go to my website voidarounds.com, go to Qt and it's gonna be way, way, way at the back here. I'll try to get that uploaded tonight. Last but certainly not least, this site's 100% funded by your donations. If you feel like sending me a sizeable birthday gift like a Porsche or a Ferrari, feel free. And be sure to visit the Voidrums Facebook group for, well, we've got like 280 programmers in there. We just chat about every language known to man from Java, Python, C++, C-sharp, Qt. Qt's not really language, but you know what I mean. Anyways, thanks for watching.