 okay can everybody hear me okay just checking that everything is up and running properly okay I'm going to assume that people are seeing this okay and that people are hearing this okay if anybody's got any comments thoughts anything else you can put them into the YouTube chat or the WhatsApp chat I will be watching both of them if you guys are watching drop a comment in YouTube so that I know kind of what my stats are at the moment because I can't actually see how many people are watching etc and I'm just gonna be hoping that this is working okay okay so what I'm gonna be doing tonight is the start of writing something which is basically a BGP LS client now BGP link status of rooting demon it uses TCP and shouldn't be that difficult to get up and running and yes I work with JetBrains IDE because quite frankly when you're doing a large project like this along with its remote development capabilities it works pretty well now I've already created a project in this the first thing that I'm gonna need to do here is I need a CMake file the thing is when you're doing any large project and by the time this is done it's gonna be pretty large you really don't want to be just doing it all in a single file so you want a decent kind of CMake file that you can build on and quite frankly CMake is just cool so let's start there we're gonna be using 318 which is what I typically use we're gonna call this BGP LS we're gonna set C standard to 99 and I'll explain some of the flags that I typically use O3 get the compiler to optimize it G3 so that I've got my debugger and that no address of packed member is because I'm gonna be using packed structures at some point and I still need to be able to take pointers to members of the structures effectively when you're writing in C normally the compiler will pad your structures to memory alignment boundaries unless you explicitly tell it to pack a structure in which case there is no padding but that can create compiler warnings when you start trying to take point of references to things inside packed structures and cause you a little bit of headache so I'm just gonna tell the compiler to pretty much ignore that by the way if anybody's got any questions as I go please just put them in the YouTube comments or alternatively in what's that next thing I'm gonna add an executable now this I'm going to add an executable for main dot C and we'll start with TCP dot C main dot C I'm gonna create purely just as something to run what I'm doing TCP dot C is going to be the start of it because I'm going to need to create a effective server here I try and keep my main to basically a BAM minimum and put everything in separate files where I can easily find it it makes it a lot easier for large projects then I'm gonna go and create main dot C I don't need an associated header and I'm gonna go and create a new source TCP dot C this one I will need a header for and at that point you'll see that my project is saying that it's not configured yet and I've got an error with my C make minimum required because we should say version and if I reload this I've got a clean C make file at that point I've got my main dot C I've got my TCP dot C I've got my TCP dot H now when I'm building TCP typically speaking TCP has sockets it has a dress length it's got the socket address it's got the socket itself and because this is multiplexed okay so let me answer that quickly why the preference of C make over make C make is a thousand times more powerful it allows me to do stuff like doxy-gen it allows me to do a lot more conditional compilation a lot more easily C make is really really powerful and it's just easier and cleaner than make as well you can actually use C make to generate make files or you can use C make with something like ninja you can use C make with me son so see make just more flexible just better I hope that answers the question as I said with regards to TCP there are a bunch of things here so we'll start with a header because when you're creating stuff for TCP I've prefer where possible to define my header structures before I start actually writing code so we'll start and we're going to need a socket structure now socket structure the reason that I do this is because I'm going to be making this thing to work with both IPv4 and IPv6 for and before I can do that I need to include a whole bunch of stuff here with I'm gonna need for later I'm gonna need my timing I'm gonna need socket age I'm gonna need tights I'm gonna need dh I'm gonna need standard boolean I'm gonna need urns ID I'm probably gonna need generic typing this next one I'm gonna use the dpdk spin lock library because it's just well easier than trying to write my own spin lock right now other thing I'm gonna need listen port is 179 I'm trying to think there's anything else I need okay I don't think so that should do because a socket can't really be v4 and v6 at the same time what it technically can but best to just put them into a union that you don't use more memory than you need to you need to be able to store the length of the address the address of the socket now keep in mind that because a v6 address is much longer than a v4 address you can make the socket rest the v6 length and you'll have enough space for both and then you've got your socket itself which is just an integer so that'll be fine your actual kind of TCP socket structure then I'm gonna need session so a session is an actual TCP session that is associated with a socket so that will contain my socket structure we probably want to create a client as well that differentiates between server sockets and client sockets because this thing technically will be able to do both both a active and a passive session which is why I will add a Boolean there what I mean by an active session is I am connecting to the router on a passive session the router is connecting to me I need to be able to differentiate those because in BGP the way the protocol works is there is a different handshake sequence dependent on who establishes the session this is also BGP based so I need to put timers in here for next lead try I want to know when the session was established I want a receive buffer we'll call that red buff I'm going to find buffer size up here maximum NTU on a normal Ethernet connection is really unlikely to be over 9200 bytes so we're just gonna call that 9200 and be done with it we're gonna create a send buffer that will also be 9200 bytes in size now there are a couple of ways that I can build a TCP server in this particular case I'm probably gonna thread it so I will add this if I decide not to use the threads later on in the code I can always just delete this then I want to make this a double link list makes it easier to find delete remove sessions and I'm just looking to see if there are and I'll add a boolean that will allow me to signal if this thing is done or not let's see so I've got my structures defined it's worth actually splitting this just so that I can keep track of what I'm doing so anyone got any questions about what I've done so far pretty standard structure definitions etc. WhatsApp or YouTube otherwise I shall continue okay so the first thing I need to do if I'm creating a TCP server is to create a function that is effectively going to listen on the thread we'll listen for sockets now the first thing that I'm going to do here is because I'm probably going to be threading this my function definition has to be of a void type because pthreads require void type functions let me just double check that before I light you all yeah so now that handler is as you'll notice is a void now I probably need a handler a handler struct as well there so see so the thread handler structure is basically there so that I can effectively read information about all my threads outside of my listener etc. and first thing I do is put a the thread handler is also basically by the way going to be largely global will be passed from main I put the boolean shutdown in there because it allows me from outside of the thread to set that and effectively shut down the whole damn program without a heartbreak on the threat then I am going to put a struct and I'll explain what this neighbor is in a second it's a BGP kind of specific structure I'll create now and then I want a neighbor count to know how many neighbors a neighbor thread will neighbor structure would look something to this effect just double checking something quickly you would have a pure IP which we're gonna make as a character a child for now you'll have a local IP so these will be this will be the IP of the router that's allowed to connect to me or that I and yes it's being recorded for the guy who just asked me in what's out basically with BGP you have your pure IP that's the router you're connecting to or the router you're connecting from your local IP is so that if you have multiple IP addresses on the box that you're working on you know that you want to listen for from a specific IP BGP also requires that you declare what your router ID is this again is normally in the form of an IPv4 address so we'll just make this a 255 character string just a little bit of space you'll also have your local autonomous system number that again is BGP specific and I'll explain it when we get there you'll have your autonomous system number of your peer then things get a little bit more complicated I'm just trying to think of the best way to do this we're gonna make this a single address family and a single sub address family again these are BGP terms let me add a comment in here so all of the stuff is derived from the BGP standard which is RFC 4270 I think it's RFC 4271 let me just verify that yeah RFC 4271 which by the way I can show you what that looks like see if I can if the screen goes blank for a second it's just because I am about to see if I can add this okay not a problem but anyway you can go and look up RFC 4271 and it will it's available added to the comments actually that one over there so that's a basic neighbor we also want to allow somebody to shut down the neighbor we want a keep alive time because BGP requires that I send keep alive and these two I'm gonna comment out for now because I'm not gonna define them straight away but I know that I'm gonna need them kind of later on in the game basically with BGP because BGP when you're receiving the packet they don't always arrive aligned so you almost have to put this through another queue so that you get correctly aligned packets otherwise things are gonna break pretty badly then so we have our thread handler now keep in mind that because I'm passing this in as a voyage to be able to use it at all I'm gonna need to cost it so strut red handle handler equals handler that basically just make a pointer to the same void pointer so that I can easily access it effectively then I need a res that's basically a result structure then missing something here you'll see that I created my sessions here but I also need another structure called TCP listen which has my main listening socket on it my main server socket a list of connected sessions we'll track the last session in the list because it just makes it easier when I'm adding new things and put a spin lock on it because I don't really want to screw with that link list on the session list without having things locked because if I do that I'm gonna create problems then it just creates me a basic variable on so that I've got something to compare with etc then basically that'll just give me a half a second time for when I need to sleep and that's because some of these functions don't take times back we'll add a time valve TV so the difference between this this is in nanoseconds and this is in usax which is yeah I may not need one of those but I'll define but anyway for now just in case and I can always delete them later then I want my basic session and first thing that I want to do so listener if you look where I allocate that if not listener so if the cutoff fails then listeners automatically gonna be null so I can just say that what I tend to do when I'm printing error logs when I'm coding like this and I can always go back and change it is I tend to print the name of the functions called it so that I know where that debug log comes from if I make the the logging messages such that if I'm hitting error I know where the log came from and I can jump to the right point in the code just makes things easier when you start running etc now this here is gonna return a standard error so I'm gonna for now and then I'm going to return null now I could technically return a structure with more errors in it from the thread because the thread is a void pointer type so I can return anything but because this is just my listener I'm already printing an error I don't really need to return anything else I'm just gonna return a null on this one now because I want this thing to listen on both v4 and v6 if I listen on an IPv6 family I can actually listen for both of the same time so if I this now it's interesting the client doesn't pick this up to the IDE doesn't pick this up terribly well because of unions etc but it does work this is AF I need six server oh that's why sorry since six ports now in networking everything is working in big Indians so if you look back at where I defined this here I did a definition of port 179 keep in mind that that is in little Indian order because this is a UN 16 and so I have to swap this yes Charlie I do not use malloc because malloc does not zero allocate Charlie just commented in the WhatsApp that I prefer to use caloc instead of malloc anybody who uses malloc while caloc exists needs to be shot because caloc will zero initialize and allocating memory that isn't zero initialized can lead you to all sorts of problems so for the love of God please can people stick to caloc rather than malloc and sorry about the fan noise it should shut up in a second it's just my router decided to wake up and get crumpy about the heating yeah sorry sorry about the background noise not much can you guys still hear me okay am I still audible there we go shut up okay then so effectively I'm telling it now that in 680 are any will allow it to listen on any any port on any address bound to the box when I create the socket then I need to create a listener socket this is a streaming socket because I'm just gonna get streaming data in from the socket tested for an error TCP listener bail basically if I can't create the listening socket I'm done then typically when I'm working with sockets like this I will set certain socket options on this thing this is a socket basically the reason that you do this is because when a TCP socket when you close the application and have to restart it some of the time it takes Linux kernel of all while to release the socket this will basically allow the socket to be grabbed again so that you can restart the application without your socket being in a fin weight or a reset weight state which can end up with you not being able to restart your application for a couple minutes until the kernel decides to clean itself up that creates me a network socket up until this point now the next thing I have to do is tell it that I actually want to listen on the socket so listen also and I want to know how many sockets I'm prepared to kind of queue up before I accept them I'm just gonna say that I'm gonna allow for 10 in my queue and my typing is terrible and I will bail if I can't do that now I've created my socket I've listened on my socket and okay so I just got asked what I'm trying to do with the code Joe I'm effectively writing a BGP demon to get and receive routing information from routers using the BGP protocol this first part of the code is me doing the TCP work to effectively create a TCP server that is at least vaguely vaguely resilient to errors etc. I hope that answers the question now you guys all remember that when I created that handler structure I put a shut down Boolean in it keep in mind that this listener thing is running in a thread and I need to be able to actually tell this whole thing to shut down in the event of me hitting control C or whatever oh here goes my router again sorry for the noise but let me continue anyway so effectively this is saying while that shutdown is not true keep going and then I'll explain this in a second so effectively this polar here what am I missing here put an error over here so see what that is because remember I paused in-hand list I'm actually using hndl or over here hndl or and this should be a poll fd and the other thing that I forgot here is that I need to I'm just checking something also going to need to include into here there we go some of this polling stuff requires GNU source because I'm using certain GNU source specific functions so I have to define this the IDE tends to bitch and whine that it's never used but it is actually used because it actually tells the thing to compile the GNU source so just ignore that so basically I am creating a polling structure which I'm going to use to poll for new connections effectively then I'm going to find out a flycode not quite sure why this thing is whining but it's whining but well we'll ignore that for now now this is basically polling the socket that I'm listening on to effectively say is anybody trying to connect to me and it's got a timeout the reason that I put a timeout here and don't just let it hang around waiting for it to poll is because if I hit control C or something I wanted to test this while loop so I'm just going to tell this thing to keep timing out and then it'll just keep polling once it's finished timing out there is only one file descriptor in the polar pointer here that's why number of file descriptors is set as one you can actually create an entire array of pollers as a pointer array and then you can listen on multiple sockets at the same time and poll them at the same time I'm only using one at the moment test the return code the return code is what poll will put in this thing and I'm basically testing it to check whether or not I got a response from an inbound polar and I can continue if I didn't get that and I got some other event then I want to switch on the reply code and we can say this will be sockets basically if I get an error off that polar on this particular socket I've got a problem and I probably should just bail because something's gone really really wrong otherwise I will get a zero return code in which case the zero return code basically means nothing answered I got no input I got a timeout effectively and then I'm just going to repeat one loop otherwise I'm going to go into a default case and the default case I'm just trying to think here let's do this properly so we're going to call something here call call locked and I'll explain this in a minute okay now first thing is that you see I'm getting a bunch of errors here because I haven't defined call locked and I haven't defined TCP accept yet call locked is gonna look something like gonna go back to our header file here and you can generally put this at the bottom here or at the top it depends on your coding style I'm just gonna throw it in here for now missed out here because this is a macro I have to escape every line and effectively what this simply does is a fairly simple macro that basically will lock my spin lock call a function get a return value and when the function returns it will unlock the lock again and then the macro will return the result that the function gave me the reason that I do this as a macro is because if you forget to unlock or lock something at the long time you can create race conditions which can be a real pain in the arse to deal with and to fight just to everybody on the stream does everybody understand that macro or can I give some more explanation speak now or forever hold your peace what's up YouTube comment whatever I'll give it a couple of seconds so that I know that everybody is caught up because I don't know how lag the stream is and if you do get it say something so that I know the people have actually heard this okay so Franklin have you ever worked with C macros before basically you need to think of a macro as effectively what it is which is a code substitution so in C if you define something like I have there as a macro effectively what happens is it does a replace on the code so if I'm lucky here it's not actually showing me the replacement values but this cool locked will effectively get replaced by this piece of code so effectively what you will end up here is over here that funk is getting replaced by TCP accept as well as anything inside the brackets of TCP accept so the first parameter here is equivalent to this whole thing over here lock is the equivalent to my second parameter the next line this void return is because I need to effectively define a variable inside this replacement code block the macro will then call the lock against this here now parameters to function macros need to be bracketed like this which is why I've got extra brackets here and I'm making it a pointer because I need to actually lock a pointer here this will then effectively call this first parameter and store the return value in this variable it'll then unlock this lock over here and this final line here acts almost as a return for whatever I've got in this variable I'm hoping that makes sense to everybody any specific questions on that before I move on because you'll see that I use a fair number of macros like this as I go and it's kind of important that people understand so if you've got specific questions please speak now in the chat etc okay I'm gonna continue and I hope that people grasped that but the next thing here is that you'll actually see here that it's moaning that I have an undeclared function of RTE spin lock that's probably because I don't the reason that I'm trying to figure out why it's not allowing me to call that and I'll show you something else in a second so that error is now gone but I've still got an error now the funny thing is because of the macro substitution if I look at my errors here I start seeing errors all on my line 59 you don't actually see a lot of those errors on line 59 because it's going to treat this whole macro as line 59 in the code so it does get a little bit of pain in the ass to debug some of these macros sometimes to figure out where the error actually is in the macro but it is what it is you'll see there for example it's saying incompatible integer to pointer conversion type the reason it's saying that is because my TCP accept function doesn't exist yet ret is defined as a pointer the default return for a non-existent function would be an integer so therefore throw a warning that I'll ever will change the moment that I go and define this TCP accept function which I'm going to do right about now now the other thing about the TCP accept function I'm never going to be calling TCP accept from outside of TCP dot see and I don't really want anyone to do that so I'm going to declare this as a static it's expand this a bit because function definition and I'll just put a default return the reason that I've done that is just to show you that suddenly down over here the moment that that function is defined I no longer have an error on my TCP accept because it's accepting it and my macro itself is now functioning because it can see it but I've still got an error on session handler over here and that would be because I didn't actually define my session handler check something okay so this p3 create is going to call another function called session handler which will actually be my main handling session so what I'm going to first do is I'm going to accept it create a session and then pass it to my session handler so I can actually comment that out for now and you'll see that I've got no more errors in the code up over here but first I need to create the TCP accept function the TCP accept function so the first thing I need to do is create a socket structure helps if I don't make typos you need to tell it again telling it what function I'm calling this in socket so if I can't allocate for the TCP socket just bail because something broke but it doesn't like that so I have made a typo over here and that's okay I just want to make sure typo something oh here we go so that will allocate for the TCP now remember I said that I'm accepting this on both v4 and v6 so I effectively need to know now whether or not this is a v6 or a v4 and I'm gonna kind of cheat a little bit here so firstly I'm gonna go and get the peer name six you'll notice that I do a lot of error printing in my code I do that because believe me it's easier than not having an error at all the next thing that I want to do here and I'll explain this in a second so effectively the IPv6 address is normally treated as an array of bytes but I need to know things about this in its various components which are gonna allow me to tell whether or not this is effectively a v6 address or a v4 address and I can do that by effectively casting parts of the address into various bits and pieces which you will see in a second so I know that if this is a v6 address then the first part of my v6 address the first UN64 is probably not going to be all zeros neither is the second UN16 here and the third is going to be like that that will effectively tell me that if the first 10 bytes of the v6 address field of all zero and the next two bytes are set at 0xFFFF that is going to be a IPv4 address encapsulated in an IPv6 format I believe that that is defined in RFC 4291 if not that it will be RFC 8200 but effectively this will tell me if it's a v4 or a v6 address if this is a v4 address I need to change my family to AFINET from AFINET6 which is the default that I've got up here and my v4 address will then become 32 bit of so effectively what I've said here now is if this isn't a v6 address get the v4 address and then use it to populate my character string up here with whatever the hell that address actually is and then just for good measure I can put something to tell me that I've got it otherwise I'm going to tell this thing AFINET6 that will effectively now get the name that the socket is coming in it'll get the address of the socket that's coming in from now normally if I was writing this and I wasn't doing this I apologize if this is more than rocket science frankly is everybody else following along here or should I take a bit of a break and continue this a little bit later what would people prefer please let me know in the YouTube comments or on WhatsApp I've had a request to kind of take a break possibly until tomorrow so that people can digest all of this so far thoughts I will go with the popular opinion okay I'm going to take a break for today I shall come back I shall leave this exactly where we left off and people can check it out etc and I will do part 2 of this tomorrow evening so I hope that was useful and we shall continue tomorrow thanks very much