Files
cws/notes/basic-concepts.md

118 lines
4.4 KiB
Markdown

# Basic concepts
Before reading, this document could contain errors, please check everything you read.
- [Basic concepts](#basic-concepts)
- [Socket](#socket)
- [Internet sockets](#internet-sockets)
- [Byte Order](#byte-order)
- [Structs](#structs)
- [struct addrinfo](#struct-addrinfo)
- [struct sockaddr](#struct-sockaddr)
- [struct sockaddr\_in](#struct-sockaddr_in)
- [struct sockaddr\_storage](#struct-sockaddr_storage)
- [IP Addresses](#ip-addresses)
- [getaddrinfo()](#getaddrinfo)
### Socket
When Unix programs do some I/O they do it reading/writing to a **file descriptor**. A file descriptor is an integer associated with an open file, it can be anything. To communicate over the internet using a file descriptor we'll make a call to the `socket()` system routine.
### Internet sockets
There are two types of Internet sockets:
1. Stream Sockets (SOCK_STREAM) - error-free and a realiable two-way communication (TCP)
2. Datagram Sockets (SOCK_DGRAM) - connectionless (UDP)
### Byte Order
- Big-Endian (also called **Network Byte Order**)
- Little-Endian
Before making any transmission we have to convert the byte order to a Network Byte Order, we can do this with simple functions:
| Function | Description |
| -------- | --------------------- |
| htons() | Host to Network Short |
| htonl() | Host to Network Long |
| ntohs() | Network to Host Short |
| ntohl() | Network to Host Long |
And convert the answer to the host byte order.
### Structs
#### struct addrinfo
This struct prepares the socket address strcutures for subsequent use.
```c
struct addrinfo {
int ai_flags; // AI_PASSIVE, AI_CANONNAME, etc.
int ai_family; // AF_INET, AF_INET6, AF_UNSPEC
int ai_socktype; // SOCK_STREAM, SOCK_DGRAM
int ai_protocol; // use 0 for "any"
size_t ai_addrlen; // size of ai_addr in bytes
struct sockaddr *ai_addr; // struct sockaddr_in or _in6
char *ai_canonname; // full canonical hostname
struct addrinfo *ai_next; // linked list, next node
};
```
#### struct sockaddr
Inside the struct we can see there is a pointer to the `struct sockaddr`, that is defined as follows:
```c
struct sockaddr {
unsigned short sa_family; // address family, AF_xxx
char sa_data[14]; // 14 bytes of protocol address
};
```
#### struct sockaddr_in
But, we can avoid to pack manually the stuff inside this struct and use the `struct sockaddr_in` (or `struct sockaddr_in6` for IPv6) with a fast cast that is made for the Internet:
```c
struct sockaddr_in {
short int sin_family; // Address family, AF_INET
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // Internet address
unsigned char sin_zero[8]; // Same size as struct sockaddr
};
```
`sin_zero` is used to pad the struct to the length of a sockaddr and it should be set to all zeros (`memset()`).
#### struct sockaddr_storage
This struct is designed to storage both IPv4 and IPv6 structures. Example, when a client is going to connect to your server you don't know if it is a IPv4 or IPv6 so you use this struct and then cast to what you need (check the `ss_family` first).
```c
struct sockaddr_storage {
sa_family_t ss_family; // address family
// all this is padding, implementation specific, ignore it:
char __ss_pad1[_SS_PAD1SIZE];
int64_t __ss_align;
char __ss_pad2[_SS_PAD2SIZE];
};
```
### IP Addresses
Here's a way to convert an IP address string into a struct.
```c
struct sockaddr_in sa;
struct sockaddr_in6 sa6;
inet_pton(AF_INET, "192.168.0.1", &(sa.sin_addr));
inet_pton(AF_INET6, "2001:db8:63b3:1::3490", &(sa6.sin6_addr));
```
There is a very easy function called `inet_pton()`, *pton* stands for **Presentation to network**. If you want to do the same but from binary to string you have `inet_ntop()`.
### getaddrinfo()
```c
int getaddrinfo(const char *node, // e.g. "www.example.com" or IP
const char *service, // e.g. "http" or port number
const struct addrinfo *hints,
struct addrinfo **res);
```
The `node` could be a host name or IP address. `service` could be a port number or a service found in `/etc/services` (e.g. "http" or "ftp" or "telnet").
`hints` points to a struct you already filled and `res` contains a linked list of results.