net: minor improvements in tcp client sockets
[quarnos.git] / resources / net / tcp.cpp
blobf7d9f4a4cc89b19fc856544a00a2a79ec7252aaf
1 /* Based on RFC793 */
3 #include "tcp.h"
4 #include "ipv4.h"
6 #include "arch/low/general.h"
8 #include "libs/pointer.h"
9 #include "libs/array.h"
11 #include "tcp_client_socket.h"
13 using namespace net;
15 void tcp::send(const ipv4_addr &addr, u16 dst_port, u16 src_port, const buffer &data, tcp_flags flags, int seq, int ack) {
16 p<tcp_packet> pkg = new tcp_packet;
17 pkg->sender_port = to_be16(src_port);
18 pkg->receiver_port = to_be16(dst_port);
19 pkg->seq = to_be32(seq);
20 pkg->ack = to_be32(ack);
21 pkg->header_size = sizeof(tcp_packet) << 2;
22 pkg->flags = flags;
23 pkg->window_size = to_be16(1000); /*wtf?*/
24 pkg->checksum = 0;
25 pkg->piority = 0;
28 p<pseudo_header> ph = new pseudo_header;
29 ph->source = down.cast<ipv4>()->get_my_ip().to_be();
30 ph->destination = addr.to_be();
31 ph->zero = 0;
32 ph->protocol = 6;
33 ph->length = to_be16(sizeof(tcp_packet) + data.get_size());
34 array<u16> ph_words = array<u16>::from_buffer(buffer::to_mem(ph));
36 buffer buf = buffer::to_mem(pkg);
38 buf += data;
40 array<u16> words = array<u16>::from_buffer(buf);
41 u32 sum = 0;
43 for (unsigned int i = 0; i < (sizeof(tcp_packet) + data.get_size()) / 2; i++)
44 sum += words[i];
46 if (data.get_size() % 2)
47 sum += (u16)data[data.get_size() - 1];
49 for (unsigned int i = 0; i < sizeof(pseudo_header) / 2; i++)
50 sum += ph_words[i];
52 //ph.dispose();
54 sum = (sum & 0xffff) + (sum >> 16);
55 sum += (sum >> 16);
57 buf.cast<tcp_packet>()->checksum = to_le16(~sum);
59 down->send_data(addr, 6, buf);
61 //pkg.dispose();
64 void tcp::receive(const ipv4_addr &sender, const buffer &data) {
65 p<tcp_packet> pkg = data.cast<tcp_packet>();
67 for (int i = 0; i < ports.get_count(); i++)
68 if (ports[i] == from_be16(pkg->receiver_port))
69 listeners[i](sender, from_be16(pkg->sender_port), data.cut_first(pkg->header_size >> 2), (tcp_flags)pkg->flags, from_be32(pkg->seq), from_be32(pkg->ack));
72 void tcp::listen(u16 port, port_listener listener) {
73 for (int i = 0; i < ports.get_count();) {
74 if (ports[i] == port) {
75 ports.remove(i);
76 listeners.remove(i);
77 } else
78 i++;
81 ports.add(port);
82 listeners.add(listener);
85 p<client_socket> tcp::create_client() {
86 return (client_socket*)new tcp_client_socket(this);
89 p<server_socket> tcp::create_server(int port) { }