1 #include "tcp_client_socket.h"
5 void poll(volatile int *value
, int wait_for
) {
6 while (*value
!= wait_for
) asm volatile("nop");
9 void tcp_client_socket::connect(const ipv4_addr
&addr
, int port
) {
14 client_port
= down
->acquire_port();
16 down_tcp
->listen(client_port
, tcp::port_listener::method(this, &tcp_client_socket::receive
));
20 /* TCP three-way handshake
21 * Part I: SYN packet */
23 down_tcp
->send(addr
, port
, client_port
, buffer::empty
, tcp::tcp_syn
, sequence_number
++, 0);
24 poll(reinterpret_cast<volatile int*>(&state
), established
);
27 void tcp_client_socket::receive(const ipv4_addr
&addr
, u16 sender_port
, const buffer
&data
, tcp::tcp_flags flags
, int seq
, int ack
) {
28 if (addr
!= server
|| server_port
!= server_port
)
33 if (state
== syn_sent
) {
34 /* In the second part of handshake we should receive SYN/ACK packet */
35 if (flags
!= (tcp::tcp_syn
| tcp::tcp_ack
)/* || ack != sequence_number - 1*/)
38 /* TCP three-way handshake
39 * Part III: ACK packet */
41 down_tcp
->send(addr
, sender_port
, client_port
, buffer::empty
, tcp::tcp_ack
, sequence_number
++, seq
+ 1);
43 } else if ((state
== fin_wait1
|| state
== fin_wait2
) && flags
== (tcp::tcp_fin
| tcp::tcp_ack
)) {
45 } else if (state
== fin_wait1
&& flags
== tcp::tcp_ack
) {
47 } else if (state
== established
&& flags
== tcp::tcp_fin
) {
49 down_tcp
->send(server
, server_port
, client_port
, buffer::empty
, (tcp::tcp_flags
)(tcp::tcp_fin
| tcp::tcp_ack
), sequence_number
++, ack
+ 1);
50 } else if (state
== last_ack
&& flags
== tcp::tcp_ack
) {
54 if (state
== established
) {
55 incoming_data
.push(data
.copy());
59 tcp_client_socket::tcp_client_socket(p
<transport_layer
> tl
) : client_socket(tl
), down_tcp(tl
.cast
<tcp
>()) { }
60 tcp_client_socket::~tcp_client_socket() {
64 void tcp_client_socket::write(const buffer
&data
) {
65 if (state
== established
) {
66 down
.cast
<tcp
>()->send(server
, server_port
, client_port
, data
, (tcp::tcp_flags
)(tcp::tcp_psh
| tcp::tcp_ack
), sequence_number
, ack_number
+ 1);
67 sequence_number
+= data
.get_size() > 0 ? data
.get_size() : 1;
71 void tcp_client_socket::read(buffer
&data
) {
72 if (state
== closed
|| state
== unknown
)
75 buffer buf
= incoming_data
.pop();
79 void tcp_client_socket::close() {
81 down_tcp
->send(server
, server_port
, client_port
, buffer::empty
, tcp::tcp_fin
, sequence_number
++, 0);
82 poll(reinterpret_cast<volatile int*>(&state
), closed
);
85 void tcp_client_socket::clean() {
93 // down.cast<tcp>()->remove_listener(client_port, tcp::port_listener::method(this, &tcp_client_socket::receive));
94 down
->release_port(client_port
);