From 0e0b5fb6651199fa1651810c3385fb7dd1de3482 Mon Sep 17 00:00:00 2001 From: hidnplayr Date: Sun, 13 Dec 2009 14:55:42 +0000 Subject: [PATCH] More TCP code updates for net branch, code is still very unstable git-svn-id: svn://kolibrios.org@1318 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../net/applications/telnet/telnet.asm | 34 +- kernel/branches/net/core/dll.inc | 112 ++--- kernel/branches/net/fdo.inc | 121 +++--- kernel/branches/net/network/socket.inc | 69 +++- kernel/branches/net/network/stack.inc | 19 +- kernel/branches/net/network/tcp.inc | 384 +++++++++++++++--- 6 files changed, 537 insertions(+), 202 deletions(-) diff --git a/kernel/branches/net/applications/telnet/telnet.asm b/kernel/branches/net/applications/telnet/telnet.asm index 0c644bf0f3..1a4ef61362 100644 --- a/kernel/branches/net/applications/telnet/telnet.asm +++ b/kernel/branches/net/applications/telnet/telnet.asm @@ -29,10 +29,10 @@ start: push 1 call [con_start] push title - push -1 - push -1 - push -1 - push -1 + push 25 + push 80 + push 25 + push 80 call [con_init] ; main loop push str1 @@ -102,7 +102,11 @@ main: mcall 40, 1 shl 7 ; + 7 call [con_cls] + mcall 18, 7 + push eax mcall 51, 1, thread, mem - 2048 + pop ecx + mcall 18, 3 mainloop: mcall 10 @@ -115,13 +119,25 @@ mainloop: mov byte [esi + eax], 0 @@: - cmp byte [esi], 0xff ; 'IAC' = Interpret As Command + cmp byte [esi], 0xff ; Interpret As Command jne @f ; TODO: parse options, for now, we will reply with 'WONT' to everything mov byte [esi + 1], 252 ; WONT add esi, 3 ; a command is always 3 bytes jmp @r + + @@: + cmp byte [esi], 0x1b ; escape character + jne @f + cmp word [esi+1], 0x485b ; move cursor to beginning + jne @f + push 0 + push 0 + call [con_set_cursor_pos] + add esi, 3 + + @@: push esi @@ -160,14 +176,15 @@ exit: thread: mcall 40, 0 + .loop: call [con_getch2] mov byte [send_data], al mcall send, [socketnum], send_data, 1 - jmp thread + jmp .loop ; data title db 'Telnet',0 -str1 db 'Telnet v0.1',10,' for KolibriOS # 1250 or later. ',10,10,0 +str1 db 'Telnet v0.1',10,' for KolibriOS # 1281 or later. ',10,10,'If you dont know where to connect to, try towel.blinkenlights.nl',10,10,0 str2 db '> ',0 str3 db 'Connecting to: ',0 str4 db 10,0 @@ -199,7 +216,8 @@ import console, \ con_exit, 'con_exit', \ con_gets, 'con_gets',\ con_cls, 'con_cls',\ - con_getch2, 'con_getch2' + con_getch2, 'con_getch2',\ + con_set_cursor_pos, 'con_set_cursor_pos' i_end: socketnum dd ? diff --git a/kernel/branches/net/core/dll.inc b/kernel/branches/net/core/dll.inc index 5e5d7b689a..a6a1244d1d 100644 --- a/kernel/branches/net/core/dll.inc +++ b/kernel/branches/net/core/dll.inc @@ -17,39 +17,39 @@ PID_KERNEL equ 1 ;os_idle thread align 4 proc attach_int_handler stdcall, irq:dword, handler:dword, access_rights:dword - push ebx + push ebx - mov ebx, [irq] ;irq num - test ebx, ebx - jz .err - cmp ebx, 15 ; hidnplayr says: we only have 16 IRQ's - ja .err - mov eax, [handler] - test eax, eax - jz .err - cmp [irq_owner + 4 * ebx], 0 - je @f + mov ebx, [irq] ;irq num + test ebx, ebx + jz .err + cmp ebx, 15 ; hidnplayr says: we only have 16 IRQ's + ja .err + mov eax, [handler] + test eax, eax + jz .err + cmp [irq_owner + 4 * ebx], 0 + je @f - mov ecx, [irq_rights + 4 * ebx] ; Rights : 0 - full access, 1 - read only, 2 - forbidden - test ecx, ecx - jnz .err + mov ecx, [irq_rights + 4 * ebx] ; Rights : 0 - full access, 1 - read only, 2 - forbidden + test ecx, ecx + jnz .err @@: - mov [irq_tab+ebx*4], eax + mov [irq_tab+ebx*4], eax - mov eax, [access_rights] - mov [irq_rights + 4 * ebx], eax + mov eax, [access_rights] + mov [irq_rights + 4 * ebx], eax - mov [irq_owner + 4 * ebx], PID_KERNEL ; all handlers belong to a kernel + mov [irq_owner + 4 * ebx], PID_KERNEL ; all handlers belong to a kernel - stdcall enable_irq, [irq] - pop ebx - mov eax, 1 - ret + stdcall enable_irq, [irq] + pop ebx + mov eax, 1 + ret .err: - pop ebx - xor eax, eax - ret + pop ebx + xor eax, eax + ret endp uglobal @@ -121,8 +121,8 @@ align 4 jmp .main ; align 4 ; .irq_6: -; push 6 -; jmp .main +; push 6 +; jmp .main align 4 .irq_7: push 7 @@ -149,16 +149,16 @@ align 4 jmp .main ; align 4 ; .irq_13: -; push 13 -; jmp .main +; push 13 +; jmp .main ; align 4 ; .irq_14: -; push 14 -; jmp .main +; push 14 +; jmp .main ; align 4 ; .irq_15: -; push 15 -; jmp .main +; push 15 +; jmp .main align 16 .main: @@ -212,7 +212,7 @@ endp align 4 proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword - push ebx + push ebx edx xor eax, eax xor ebx, ebx mov ah, byte [bus] @@ -220,13 +220,13 @@ proc pci_read32 stdcall, bus:dword, devfn:dword, reg:dword mov bh, byte [devfn] mov bl, byte [reg] call pci_read_reg - pop ebx + pop edx ebx ret endp align 4 proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword - push ebx + push ebx edx xor eax, eax xor ebx, ebx mov ah, byte [bus] @@ -234,13 +234,13 @@ proc pci_read16 stdcall, bus:dword, devfn:dword, reg:dword mov bh, byte [devfn] mov bl, byte [reg] call pci_read_reg - pop ebx + pop edx ebx ret endp align 4 proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword - push ebx + push ebx edx xor eax, eax xor ebx, ebx mov ah, byte [bus] @@ -248,13 +248,13 @@ proc pci_read8 stdcall, bus:dword, devfn:dword, reg:dword mov bh, byte [devfn] mov bl, byte [reg] call pci_read_reg - pop ebx + pop edx ebx ret endp align 4 proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword - push ebx + push ebx edx xor eax, eax xor ebx, ebx mov ah, byte [bus] @@ -263,13 +263,13 @@ proc pci_write8 stdcall, bus:dword, devfn:dword, reg:dword, val:dword mov bl, byte [reg] mov ecx, [val] call pci_write_reg - pop ebx + pop edx ebx ret endp align 4 proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword - push ebx + push ebx edx xor eax, eax xor ebx, ebx mov ah, byte [bus] @@ -278,13 +278,13 @@ proc pci_write16 stdcall, bus:dword, devfn:dword, reg:dword, val:dword mov bl, byte [reg] mov ecx, [val] call pci_write_reg - pop ebx + pop edx ebx ret endp align 4 proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword - push ebx + push ebx edx xor eax, eax xor ebx, ebx mov ah, byte [bus] @@ -293,7 +293,7 @@ proc pci_write32 stdcall, bus:dword, devfn:dword, reg:dword, val:dword mov bl, byte [reg] mov ecx, [val] call pci_write_reg - pop ebx + pop edx ebx ret endp @@ -394,7 +394,7 @@ proc reg_service stdcall, name:dword, handler:dword push ebx - xor eax, eax + xor eax, eax cmp [name], eax je .fail @@ -432,7 +432,7 @@ proc reg_service stdcall, name:dword, handler:dword ret .fail: xor eax, eax - pop ebx + pop ebx ret endp @@ -811,7 +811,7 @@ proc load_driver stdcall, driver_name:dword mov byte [edx+12], '/' mov esi, [driver_name] .redo: - lea edx, [file_name] + lea edx, [file_name] lea edi, [edx+13] mov ecx, 16 @@: @@ -928,14 +928,14 @@ proc load_driver stdcall, driver_name:dword jnz .ok stdcall kernel_free, [img_base] - cmp dword [file_name+13], 'SOUN' - jnz @f - cmp dword [file_name+17], 'D.ob' - jnz @f - cmp word [file_name+21], 'j' - jnz @f - mov esi, aSis - jmp .redo + cmp dword [file_name+13], 'SOUN' + jnz @f + cmp dword [file_name+17], 'D.ob' + jnz @f + cmp word [file_name+21], 'j' + jnz @f + mov esi, aSis + jmp .redo @@: xor eax, eax ret diff --git a/kernel/branches/net/fdo.inc b/kernel/branches/net/fdo.inc index ca9055b563..21d6c45bf8 100644 --- a/kernel/branches/net/fdo.inc +++ b/kernel/branches/net/fdo.inc @@ -61,11 +61,11 @@ macro DEBUGS_N _sign,_num,[_str] { jmp ..label ..str db _str,0 ..label: - add esp,4*8+4 - mov edx,..str - sub esp,4*8+4 + add esp,4*8+4 + mov edx,..str + sub esp,4*8+4 else - mov edx,_str + mov edx,_str end if if ~_num eq if _num eqtype eax @@ -235,74 +235,75 @@ macro DEBUGH_N _sign,_num,_hex { debug_func fdo_debug_outchar debug_beginf - pushad - movzx ebx,al - mov eax,1 - mov ecx,sys_msg_board - call ecx ; sys_msg_board - popad - ret + pushad + movzx ebx,al + mov eax,1 + mov ecx,sys_msg_board + call ecx ; sys_msg_board + popad + ret debug_endf debug_func fdo_debug_outstr debug_beginf - mov eax,1 - .l1: dec esi - js .l2 - movzx ebx,byte[edx] - or bl,bl - jz .l2 - mov ecx,sys_msg_board - call ecx ; sys_msg_board - inc edx - jmp .l1 - .l2: ret + mov eax,1 + .l1: dec esi + js .l2 + movzx ebx,byte[edx] + or bl,bl + jz .l2 + mov ecx,sys_msg_board + call ecx ; sys_msg_board + inc edx + jmp .l1 + .l2: ret debug_endf debug_func fdo_debug_outdec debug_beginf - or cl,cl - jz @f - or eax,eax - jns @f - neg eax - push eax - mov al,'-' - call fdo_debug_outchar - pop eax - @@: push 10 - pop ecx - push -'0' - .l1: xor edx,edx - div ecx - push edx - test eax,eax - jnz .l1 - .l2: pop eax - add al,'0' - jz .l3 - call fdo_debug_outchar - jmp .l2 - .l3: ret + or cl,cl + jz @f + or eax,eax + jns @f + neg eax + push eax + mov al,'-' + call fdo_debug_outchar + pop eax + @@: push 10 + pop ecx + push -'0' + .l1: xor edx,edx + div ecx + push edx + test eax,eax + jnz .l1 + .l2: pop eax + add al,'0' + jz .l3 + call fdo_debug_outchar + jmp .l2 + .l3: ret debug_endf -debug_func fdo_debug_outhex __fdo_hexdigits db '0123456789ABCDEF' +debug_func fdo_debug_outhex + debug_beginf - mov cl,dl - neg cl - add cl,8 - shl cl,2 - rol eax,cl - .l1: rol eax,4 - push eax - and eax,0x0000000F - mov al,[__fdo_hexdigits+eax] - call fdo_debug_outchar - pop eax - dec edx - jnz .l1 - ret + mov cl,dl + neg cl + add cl,8 + shl cl,2 + rol eax,cl + .l1: rol eax,4 + push eax + and eax,0x0000000F + mov al,[__fdo_hexdigits+eax] + call fdo_debug_outchar + pop eax + dec edx + jnz .l1 + ret debug_endf ;----------------------------------------------------------------------------- diff --git a/kernel/branches/net/network/socket.inc b/kernel/branches/net/network/socket.inc index b6a41c1c70..2b1a4a32b8 100644 --- a/kernel/branches/net/network/socket.inc +++ b/kernel/branches/net/network/socket.inc @@ -24,6 +24,7 @@ struct SOCKET_head .Type dd ? ; RAW/UDP/TCP/... .Protocol dd ? ; ICMP/IPv4/ARP/ .lock dd ? ; lock mutex + .errorcode dd ? .end: ends @@ -55,6 +56,7 @@ struct TCP_SOCKET ; Transmission control block .state dd ? ; TCB state .timer dd ? ; TCB timer (seconds) + .ISS dd ? ; initial send sequence number .IRS dd ? ; initial receive sequence number .SND_UNA dd ? ; sequence number of unack'ed sent Packets @@ -191,11 +193,31 @@ socket_open: mov [eax + SOCKET_head.Type], edx mov [eax + SOCKET_head.Protocol], esi + cmp ecx, AF_INET4 + je .af_inet4 + + jmp .done + + + .af_inet4: + + cmp edx, IP_PROTO_TCP + je .tcp + + jmp .done + + .tcp: + + mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSED + + pseudo_random ebx + mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.ISS], ebx + mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT], ebx + + .done: stdcall net_socket_addr_to_num, eax DEBUGF 1,", socketnumber: %u\n", eax - ; TODO: if it is a tcp socket, set state to TCB_CLOSED - mov [esp+32], eax ret @@ -513,27 +535,42 @@ socket_close: ret .tcp: + mov dword [esp+32],0 + ; first, remove all resend entries for this socket - cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN - je .destroy_tcb - cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT - je .destroy_tcb + call TCP_remove_socket - ; Send a fin, then enter finwait2 state +; cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LISTEN +; je .destroy_tcb +; cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_SENT +; je .destroy_tcb +; cmp [eac + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSED +; je .destroy_tcb + cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_SYN_RECEIVED + je .fin_wait + cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_ESTABLISHED + je .fin_wait + cmp [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT + je .last_ack + + stdcall net_socket_free, ebx + + ret + + + .last_ack: + mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_LAST_ACK + jmp .send_fin + + .fin_wait: mov [eax + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_FIN_WAIT_1 - mov bl, TH_FIN + .send_fin: + mov bl, TH_FIN + TH_ACK xor ecx, ecx -; call TCP_send + call TCP_send - ;;;;; - - - .destroy_tcb: - - stdcall net_socket_free, eax - mov dword [esp+32],0 ret diff --git a/kernel/branches/net/network/stack.inc b/kernel/branches/net/network/stack.inc index 749ad1a416..3c7ff46034 100644 --- a/kernel/branches/net/network/stack.inc +++ b/kernel/branches/net/network/stack.inc @@ -97,6 +97,23 @@ macro add_INET reg { rol ecx, 16 } + +macro pseudo_random reg { + + add reg, [esp] + rol reg, 5 + xor reg, [timer_ticks] + imul reg, 214013 + xor reg, 0xdeadbeef + rol reg, 9 + + pushd reg + mov word [esp], 0x8080 ; kernel heap start addr (os_stack) + xor reg, [esp] + add esp, 4 + +} + include "queue.inc" include "ARP.inc" include "IPv4.inc" @@ -152,7 +169,7 @@ stack_handler: cmp [ETH_RUNNING], 0 je .exit - ; Test for 1/100 s (10ms) tick + ; Test for 10ms tick mov eax, [timer_ticks] cmp eax, [last_1hsTick] je .exit diff --git a/kernel/branches/net/network/tcp.inc b/kernel/branches/net/network/tcp.inc index c22036adbe..4896b757cb 100644 --- a/kernel/branches/net/network/tcp.inc +++ b/kernel/branches/net/network/tcp.inc @@ -8,6 +8,7 @@ ;; Part of the tcp/ip network stack for KolibriOS ;; ;; ;; ;; Written by hidnplayr@kolibrios.org ;; +;; Inspired by the TCP code of Mike Hibbit for MenuetOS ;; ;; ;; ;; GNU GENERAL PUBLIC LICENSE ;; ;; Version 2, June 1991 ;; @@ -22,6 +23,8 @@ TCP_PACKET_TTL equ 50 ; resend if not replied to in 1/100 s TCP_SOCKET_TTL equ 10 ; # of secs to wait before closing socket TCP_QUEUE_SIZE equ 16 +TCP_MAX_ACKS equ 16 + struct TCP_Packet .SourcePort dw ? @@ -63,13 +66,16 @@ uglobal TCP_PACKETS_RX rd MAX_IP TCP_IN_QUEUE rd (tcp_in_queue_entry.size*TCP_QUEUE_SIZE+queue.data)/4 - TCP_OUT_QUEUE dd ? + TCP_OUT_QUEUE dd ?, ? rd (tcp_out_queue_entry.size*TCP_QUEUE_SIZE)/4 + + TCP_ACKS dd ? + TCP_ACK_LIST rd 3*TCP_MAX_ACKS endg align 4 iglobal -stateHandler: +TCPstateHandler: dd stateTCB_LISTEN dd stateTCB_SYN_SENT @@ -114,7 +120,7 @@ TCP_init: xor eax, eax mov esi, TCP_OUT_QUEUE - mov ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+1 + mov ecx, TCP_QUEUE_SIZE*tcp_out_queue_entry/4+2+2+3*TCP_MAX_ACKS rep stosd ret @@ -193,9 +199,12 @@ TCP_send_queued: cmp [TCP_OUT_QUEUE], 0 je .exit + mov ebx, TCP_OUT_QUEUE+4 + call wait_mutex + mov eax, TCP_QUEUE_SIZE mov ecx, [TCP_OUT_QUEUE] - mov esi, TCP_OUT_QUEUE+4 + mov esi, TCP_OUT_QUEUE+8 .loop: cmp [esi + tcp_out_queue_entry.data_ptr], 0 @@ -203,30 +212,33 @@ TCP_send_queued: add esi, tcp_out_queue_entry.size loop .loop .exit: + mov [TCP_OUT_QUEUE+4], 0 ret .found_one: dec [esi + tcp_out_queue_entry.ttl] jz .send_it + cmp [esi + tcp_out_queue_entry.data_ptr], -1 + jz .is_ack .find_next: add esi, tcp_out_queue_entry.size dec eax jz .exit test ecx, ecx jnz .loop + mov [TCP_OUT_QUEUE+4], 0 ret .send_it: - push eax ecx esi - + pusha mov ebx, [esi + tcp_out_queue_entry.owner] - push [esi + tcp_out_queue_entry.data_size] - push [esi + tcp_out_queue_entry.data_ptr] + pushd [esi + tcp_out_queue_entry.data_size] + pushd [esi + tcp_out_queue_entry.data_ptr] DEBUGF 1,"Now sending TCP packet %x, size: %u, owner: %x, sendproc %x\n", [esp], [esp+4], ebx, [esi + tcp_out_queue_entry.sendproc] inc [TCP_PACKETS_TX] call [esi + tcp_out_queue_entry.sendproc] add esp, 8 - pop esi ecx eax + popa dec [esi + tcp_out_queue_entry.retries] jz .remove_it @@ -241,6 +253,17 @@ TCP_send_queued: dec [TCP_OUT_QUEUE] jmp .find_next + .is_ack: + pusha + mov eax, [esi + tcp_out_queue_entry.socket] + mov ebx, [esi + tcp_out_queue_entry.owner] + mov ecx, [esi + tcp_out_queue_entry.size] + call TCP_send_ack + popa + mov [esi + tcp_out_queue_entry.data_ptr], 0 + dec [TCP_OUT_QUEUE] + jmp .find_next + ;----------------------------------------------------------------- @@ -266,9 +289,11 @@ TCP_handler : ; TODO: validate checksum +; Find a matching socket for received packet, all following expressions must be valid: +; ; IP Packet TCP Destination Port = local Port -; IP Packet SA = Remote IP OR = 0 -; IP Packet TCP Source Port = remote Port OR = 0 +; (IP Packet SA = Remote IP) OR (Remote IP = 0) +; (IP Packet TCP Source Port = remote Port) OR (remote Port = 0) mov ebx, net_sockets @@ -318,27 +343,30 @@ TCP_handler : ; ecx is size of tcp data ; as a Packet has been received, update the TCB timer - mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.timer], TCP_SOCKET_TTL ; If the received Packet has an ACK bit set, remove any Packets in the resend queue that this received Packet acknowledges test [edx + TCP_Packet.Flags], TH_ACK jz .no_ack ; No ACK, so no data yet -; Calculate ACK number +; Calculate ACK number, in intel byte order mov edi, [edx + TCP_Packet.AckNumber] bswap edi mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.last_ack_number], edi - DEBUGF 1,"Setting last_ack_number to %u\n", edi - bswap edi + DEBUGF 1,"Setting last_ack_number to %u\n", edi ; Dequeue all acknowledged packets cmp [TCP_OUT_QUEUE], 0 ; first, check if any packets are queued at all je .no_ack + push ebx + mov ebx, TCP_OUT_QUEUE+4 + call wait_mutex + pop ebx + push ecx - DEBUGF 1,"Removing all queued packets with smaller ACK\n" + DEBUGF 1,"Removing all queued packets with smaller ACK\n" mov ecx, TCP_QUEUE_SIZE - mov esi, TCP_OUT_QUEUE+4 + mov esi, TCP_OUT_QUEUE+8 .loop: cmp [esi + tcp_out_queue_entry.data_ptr], 0 je .maybe_next @@ -349,7 +377,7 @@ TCP_handler : cmp [esi + tcp_out_queue_entry.seq_num], edi jg .maybe_next - DEBUGF 1,"Removing a queued packet\n" + DEBUGF 1,"Removing a queued packet\n" push [esi + tcp_out_queue_entry.data_ptr] mov [esi + tcp_out_queue_entry.data_ptr], 0 @@ -359,8 +387,9 @@ TCP_handler : .maybe_next: add esi, tcp_out_queue_entry.size loop .loop - pop ecx + mov [TCP_OUT_QUEUE+4], 0 + pop ecx ; Now call the correct handler, depending on the socket state .no_ack: @@ -371,11 +400,7 @@ TCP_handler : cmp eax, TCB_CLOSED ja .dump - dec eax - shl eax, 2 - add eax, stateHandler - - call dword[eax] + call dword [TCPstateHandler+eax*4-4] .dump: DEBUGF 1,"Dumping TCP packet\n" @@ -465,13 +490,11 @@ TCP_send: xchg cl, ch pushw cx xchg cl, ch -;; pushw TCP_Packet.Data shl 8 pushw IP_PROTO_TCP shl 8 - pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options.. + pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options.. pushd [edi-8] ; source address xor edx, edx -; mov ecx, TCP_Packet.Data mov esi, edi call checksum_1 mov ecx, 12 @@ -496,14 +519,13 @@ TCP_send: and ecx, 0x0000ffff xchg cl, ch sub cx, TCP_Packet.Data - add_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT) + add_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT) ; todo: this should only happen when packet was queued successful mov ecx, TCP_RETRIES jmp .go_for_it .only_one: -; inc_INET (edi + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT) mov ecx, 1 .go_for_it: @@ -523,37 +545,37 @@ TCP_send: ; IN: [esp] pointer to buffer ; [esp + 4] size of buffer ; ebx = driver struct +; edx = sequence number of this packet in intel byte order ; esi = sender proc -; edx = sequence number of this packet in normal byte order ; edi = socket number -; ecx = retries + ; OUT: / ; ;----------------------------------------------------------------- align 4 TCP_queue: - bswap edx DEBUGF 1,"Adding packet to TCP queue, buffer: %x, size: %u, driver: %x, acknum: %u\n", [esp], [esp+4], ebx, edx - bswap edx cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE jge .full - push ecx - mov ecx, TCP_QUEUE_SIZE - mov eax, TCP_OUT_QUEUE+4 + push ebx + mov ebx, TCP_OUT_QUEUE+4 + call wait_mutex + pop ebx + mov ecx, TCP_QUEUE_SIZE + mov eax, TCP_OUT_QUEUE+8 .loop: cmp [eax + tcp_out_queue_entry.data_ptr], 0 je .found_it add eax, tcp_out_queue_entry.size loop .loop + add esp, 4 .full: ; silently discard the packet DEBUGF 1,"TCP queue is full!\n" - - add esp, 4 call kernel_free add esp, 4 @@ -561,7 +583,7 @@ TCP_queue: .found_it: ; eax points to empty queue entry - pop [eax + tcp_out_queue_entry.retries] + mov [eax + tcp_out_queue_entry.retries], TCP_RETRIES pop [eax + tcp_out_queue_entry.data_ptr] pop [eax + tcp_out_queue_entry.data_size] mov [eax + tcp_out_queue_entry.ttl], 1 ; send immediately @@ -572,9 +594,179 @@ TCP_queue: inc [TCP_OUT_QUEUE] - sub eax, TCP_OUT_QUEUE+4 - DEBUGF 1,"Added to queue in pos %u\n", eax + sub eax, TCP_OUT_QUEUE+8 + shr eax, 5 + DEBUGF 1,"Added to queue in pos %u, total queued packets: %u\n", eax, [TCP_OUT_QUEUE+8] + mov [TCP_OUT_QUEUE+4], 0 + + ret + + +;----------------------------------------------------------------- +; +; IN: ebx = socket +; ecx = ack number +; +; OUT: / +; +;----------------------------------------------------------------- +align 4 +TCP_queue_ack: + + DEBUGF 1,"Adding ACK to TCP queue, socket: %x, acknum: %u\n", ebx, ecx + + cmp [TCP_OUT_QUEUE], TCP_QUEUE_SIZE + jge .full + + push ebx ecx + mov ebx, TCP_OUT_QUEUE+4 + call wait_mutex + + mov ecx, TCP_QUEUE_SIZE + mov eax, TCP_OUT_QUEUE+8 + .loop: + cmp [eax + tcp_out_queue_entry.data_ptr], 0 + je .found_it + add eax, tcp_out_queue_entry.size + loop .loop + + add esp, 8 + .full: ; silently discard the packet + DEBUGF 1,"TCP queue is full!\n" + ret + + .found_it: ; eax points to empty queue entry + + pop [eax + tcp_out_queue_entry.data_size] ; ACK number + mov [eax + tcp_out_queue_entry.data_ptr], -1 ; ACK packet + pop [eax + tcp_out_queue_entry.socket] + mov [eax + tcp_out_queue_entry.retries], 1 + mov [eax + tcp_out_queue_entry.ttl], 20 ; 200 ms + + inc [TCP_OUT_QUEUE] + + sub eax, TCP_OUT_QUEUE+8 + shr eax, 5 + DEBUGF 1,"Added to queue in pos %u, total queued packets: %u\n", eax, [TCP_OUT_QUEUE+8] + + mov [TCP_OUT_QUEUE+4], 0 + + ret + + +; IN: eax = socket pointer +; ebx = device structure +; ecx = ack number + +align 4 +TCP_send_ack: + + DEBUGF 1,"Creating TCP ACK packet, socket: %x, acknum: %x\n", eax, ecx + + push ecx eax + + mov di , IP_PROTO_TCP + mov ecx, TCP_Packet.Data +; Create an IPv4 Packet of the correct size + mov ebx, [eax + SOCKET_head.end + IPv4_SOCKET.LocalIP] + mov eax, [eax + SOCKET_head.end + IPv4_SOCKET.RemoteIP] + + call IPv4_create_packet + cmp edi, -1 + je .fail + + pop ecx + +; fill in tcp sequence number + push [ecx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.SND_NXT] + pop [edi + TCP_Packet.SequenceNumber] + +; Fill in local and remote ports + push dword [ecx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.LocalPort] + pop dword [edi + TCP_Packet.SourcePort] + +; Acknumber + pop [edi + TCP_Packet.AckNumber] + +; Fill in other tcp options + mov [edi + TCP_Packet.Flags], TH_ACK + mov [edi + TCP_Packet.Window], 0x0005 ; 1280 bytes + mov [edi + TCP_Packet.UrgentPointer], 0 + mov [edi + TCP_Packet.DataOffset], 0x50 + mov [edi + TCP_Packet.Checksum], 0 + +; Push pointer to and size of total packet (needed for send procedure) + push edx eax esi + +; Now, calculate the checksum + pushw TCP_Packet.Data shl 8 + pushw IP_PROTO_TCP shl 8 + pushd [edi-4] ; destination address ; TODO: fix this, IPv4 packet could have options.. + pushd [edi-8] ; source address + + xor edx, edx + mov ecx, 12 + mov esi, esp + call checksum_1 + call checksum_2 + mov [edi + TCP_Packet.Checksum], dx + add esp, 12 ; remove the pseudoheader from stack + + pop eax + call eax + call kernel_free + add esp, 4 ; pop (balance stack) + ret + + .fail: + add esp, 8 + ret + + + + +;----------------------------------------------------------------- +; +; Remove all queued TCP packets for a specified socket +; +; IN: eax = socket number +; OUT: / +; +; destoys esi and ecx +; +;----------------------------------------------------------------- + +align 4 +TCP_remove_socket: + + cmp [TCP_OUT_QUEUE], 0 + je .skip + + mov ebx, TCP_OUT_QUEUE+4 + call wait_mutex + + mov eax, TCP_QUEUE_SIZE + mov ecx, [TCP_OUT_QUEUE] + mov esi, TCP_OUT_QUEUE+8 + + .loop: + cmp [esi + tcp_out_queue_entry.data_ptr], 0 + jz .maybenext + cmp [esi + tcp_out_queue_entry.socket], eax + jnz .maybenext + + push [esi + tcp_out_queue_entry.data_ptr] + mov [esi + tcp_out_queue_entry.data_ptr], 0 + dec [TCP_OUT_QUEUE] + call kernel_free + + .maybenext: + add esi, tcp_out_queue_entry.size + loop .loop + + mov [TCP_OUT_QUEUE+4], 0 + .skip: ret @@ -737,6 +929,90 @@ stateTCB_SYN_RECEIVED: ret +if 0 + + +align 4 +stateTCB_ESTABLISHED: + + DEBUGF 1,"TCBStateHandler: Established\n" + + mov eax, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] + bswap eax + DEBUGF 1,"RCV_NXT is set to:%u\n", eax + bswap eax + cmp eax, [edx + TCP_Packet.SequenceNumber] + jne .exit ;;;;;; + +; check if we received an ACK + test [edx + TCP_Packet.Flags], TH_ACK + jz .no_ack + + mov ax, [edx + TCP_Packet.Window] + xchg al, ah + cmp ax, 1024 + ja @f + mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.wndsizeTimer], 1 + @@: + .no_ack: + +; Now, see if we received any data + test ecx, ecx + jz .nodata + +; Calculate next sequencenumber + add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT) + + push edx + DEBUGF 1,"Got %u bytes data!\n", ecx +; calculate header length + movzx eax, [edx + TCP_Packet.DataOffset] + and eax, 11110000b + shr eax, 2 + DEBUGF 1,"TCP header size: %u\n", eax + add edx, eax ; now edx points to data + + add esp, 4 + pop esi ; pointer to buffer + add esp, 4 + + sub edx, esi + mov edi, edx ; offset + mov eax, ebx ; socket ptr + + call socket_internal_receiver ; Place the data from packet into socket + +; lea ebx, [eax + SOCKET_head.lock] +; call wait_mutex + mov ebx, eax + pop edx + + test [edx + TCP_Packet.Flags], TH_FIN + TH_RST + jz .ack + + .nodata: + test [edx + TCP_Packet.Flags], TH_FIN + TH_RST + jz .exit + +; Send an ACK to that fin, and enter closewait state + mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT +; Remove all resend entries from the queue + mov eax, ebx + call TCP_remove_socket + + .ack: + push ebx + mov ecx, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] + call TCP_queue_ack + pop ebx + + .exit: + mov [ebx + SOCKET_head.lock], 0 + ret + + +end if + align 4 stateTCB_ESTABLISHED: @@ -751,13 +1027,9 @@ stateTCB_ESTABLISHED: jne .exit ; Calculate next sequencenumber -;; test ecx, ecx -;; jnz @f -;; inc ecx -;; @@: add_INET (ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT) - test [edx + TCP_Packet.Flags], TH_FIN + TH_RST ;;; + test [edx + TCP_Packet.Flags], TH_FIN + TH_RST jnz .fin .check_ack: @@ -799,9 +1071,9 @@ stateTCB_ESTABLISHED: call socket_internal_receiver ; Place the data from packet into socket - lea ebx, [eax + SOCKET_head.lock] ;;;;; - call wait_mutex ;;;;; - mov ebx, eax ;;;; + lea ebx, [eax + SOCKET_head.lock] + call wait_mutex + mov ebx, eax .ack: mov eax, ebx @@ -814,7 +1086,7 @@ stateTCB_ESTABLISHED: mov [ebx + SOCKET_head.lock], 0 ret - .fin: + .fin: ; we received a FIN or RESET ; Remove all resend entries from the queue mov ecx, TCP_QUEUE_SIZE mov esi, TCP_OUT_QUEUE+4 @@ -837,11 +1109,10 @@ stateTCB_ESTABLISHED: loop .removeloop ; Send an ACK to that fin, and enter closewait state - mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSE_WAIT + mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_CLOSING jmp .check_ack - align 4 stateTCB_FIN_WAIT_1: @@ -864,10 +1135,6 @@ stateTCB_FIN_WAIT_1: mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT @@: - -; lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] -; inc_INET esi - ; Send an ACK mov eax, ebx mov bl, TH_ACK @@ -893,11 +1160,6 @@ stateTCB_FIN_WAIT_2: ; Change state, as we have a fin mov [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.state], TCB_TIMED_WAIT - lea esi, [ebx + SOCKET_head.end + IPv4_SOCKET.end + TCP_SOCKET.RCV_NXT] - inc_INET esi - - mov [ebx + SOCKET_head.lock], 0 - ; Send an ACK mov eax, ebx mov bl, TH_ACK