Subversion Repositories Kolibri OS

Rev

Rev 2465 | Rev 3589 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2465 Rev 3555
Line 1... Line 1...
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
2
;;                                                                 ;;
3
;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;;
3
;; Copyright (C) KolibriOS team 2004-2013. All rights reserved.    ;;
4
;; Distributed under terms of the GNU General Public License    ;;
4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                              ;;
5
;;                                                                 ;;
6
;;  SOCKET.INC                                                  ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                              ;;
7
;;                                                                 ;;
8
;;  Sockets constants, structures and functions                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
-
 
9
;;     and Clevermouse.                                            ;;
9
;;                                                              ;;
10
;;                                                                 ;;
10
;;  This file contains the following:                           ;;
-
 
11
;;    is_localport_unused                                       ;;
-
 
12
;;    get_free_socket                                           ;;
-
 
13
;;    socket_open                                               ;;
11
;;       Based on code by mike.dld                                 ;;
14
;;    socket_open_tcp                                           ;;
-
 
15
;;    socket_close                                              ;;
-
 
16
;;    socket_close_tcp                                          ;;
-
 
17
;;    socket_poll                                               ;;
-
 
18
;;    socket_status                                             ;;
-
 
19
;;    socket_read                                               ;;
-
 
20
;;    socket_write                                              ;;
-
 
21
;;    socket_write_tcp                                          ;;
-
 
22
;;                                                              ;;
12
;;                                                                 ;;
-
 
13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
-
 
14
;;          Version 2, June 1991                                   ;;
23
;;                                                              ;;
15
;;                                                                 ;;
24
;;  Changes history:                                            ;;
-
 
25
;;   22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net          ;;
-
 
26
;;   11.11.2006 - [Johnny_B] and [smb]                          ;;
-
 
27
;;                                                              ;;
-
 
28
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 
17
 
-
 
18
$Revision: 3555 $
Line 29... Line -...
29
 
-
 
Line 30... Line -...
30
$Revision: 2465 $
-
 
31
 
19
 
32
; socket data structure
-
 
-
 
20
 
33
struct  SOCKET
21
struct  SOCKET
34
        PrevPtr        dd ? ; pointer to previous socket in list
22
 
-
 
23
        NextPtr                 dd ? ; pointer to next socket in list
-
 
24
        PrevPtr                 dd ? ; pointer to previous socket in list
-
 
25
        Number                  dd ? ; socket number
-
 
26
 
35
        NextPtr        dd ? ; pointer to next socket in list
27
        mutex                   MUTEX
36
        Number         dd ? ; socket number (unique within single process)
28
 
37
        PID            dd ? ; application process id
29
        PID                     dd ? ; process ID
38
        LocalIP        dd ? ; local IP address
30
        TID                     dd ? ; thread ID
-
 
31
        Domain                  dd ? ; INET/LOCAL/..
39
        LocalPort      dw ? ; local port
32
        Type                    dd ? ; RAW/STREAM/DGRAP
40
        RemoteIP       dd ? ; remote IP address
33
        Protocol                dd ? ; ICMP/IPv4/ARP/TCP/UDP
-
 
34
        errorcode               dd ?
-
 
35
        device                  dd ? ; driver pointer, socket pointer if it's an LOCAL socket
-
 
36
 
41
        RemotePort     dw ? ; remote port
37
        options                 dd ?
-
 
38
        state                   dd ?
42
        OrigRemoteIP   dd ? ; original remote IP address (used to reset to LISTEN state)
39
        backlog                 dw ? ; how many incoming connections that can be queued
43
        OrigRemotePort dw ? ; original remote port (used to reset to LISTEN state)
40
 
-
 
41
        snd_proc                dd ?
-
 
42
        rcv_proc                dd ?
-
 
43
 
-
 
44
ends
-
 
45
 
-
 
46
struct  IP_SOCKET               SOCKET
-
 
47
 
-
 
48
        LocalIP                 rd 4 ; network byte order
-
 
49
        RemoteIP                rd 4 ; network byte order
-
 
50
 
-
 
51
ends
-
 
52
 
44
        rxDataCount    dd ? ; rx data count
53
struct  TCP_SOCKET              IP_SOCKET
45
        TCBState       dd ? ; TCB state
54
 
-
 
55
        LocalPort               dw ? ; network byte order
-
 
56
        RemotePort              dw ? ; network byte order
-
 
57
 
46
        TCBTimer       dd ? ; TCB timer (seconds)
58
        t_state                 dd ? ; TCB state
-
 
59
        t_rxtshift              db ?
-
 
60
                                rb 3 ; align
-
 
61
        t_rxtcur                dd ?
-
 
62
        t_dupacks               dd ?
-
 
63
        t_maxseg                dd ?
-
 
64
        t_force                 dd ?
-
 
65
        t_flags                 dd ?
-
 
66
 
-
 
67
;---------------
-
 
68
; RFC783 page 21
47
        ISS            dd ? ; initial send sequence
69
 
48
        IRS            dd ? ; initial receive sequence
70
; send sequence
-
 
71
        SND_UNA                 dd ? ; sequence number of unack'ed sent Packets
-
 
72
        SND_NXT                 dd ? ; next send sequence number to use
-
 
73
        SND_UP                  dd ? ; urgent pointer
-
 
74
        SND_WL1                 dd ? ; window minus one
49
        SND_UNA        dd ? ; sequence number of unack'ed sent packets
75
        SND_WL2                 dd ? ;
-
 
76
        ISS                     dd ? ; initial send sequence number
50
        SND_NXT        dd ? ; bext send sequence number to use
77
        SND_WND                 dd ? ; send window
51
        SND_WND        dd ? ; send window
78
 
-
 
79
; receive sequence
52
        RCV_NXT        dd ? ; next receive sequence number to use
80
        RCV_WND                 dd ? ; receive window
-
 
81
        RCV_NXT                 dd ? ; next receive sequence number to use
-
 
82
        RCV_UP                  dd ? ; urgent pointer
-
 
83
        IRS                     dd ? ; initial receive sequence number
-
 
84
 
-
 
85
;---------------------
-
 
86
; Additional variables
-
 
87
 
-
 
88
; receive variables
-
 
89
        RCV_ADV                 dd ?
-
 
90
 
-
 
91
; retransmit variables
-
 
92
        SND_MAX                 dd ?
53
        RCV_WND        dd ? ; receive window
93
 
-
 
94
; congestion control
-
 
95
        SND_CWND                dd ?
-
 
96
        SND_SSTHRESH            dd ?
-
 
97
 
-
 
98
;----------------------
-
 
99
; Transmit timing stuff
-
 
100
        t_idle                  dd ?
-
 
101
        t_rtt                   dd ?
-
 
102
        t_rtseq                 dd ?
-
 
103
        t_srtt                  dd ?
-
 
104
        t_rttvar                dd ?
-
 
105
        t_rttmin                dd ?
-
 
106
        max_sndwnd              dd ?
-
 
107
 
-
 
108
;-----------------
-
 
109
; Out-of-band data
-
 
110
        t_oobflags              dd ?
-
 
111
        t_iobc                  dd ?
-
 
112
        t_softerror             dd ?
-
 
113
 
-
 
114
 
-
 
115
;---------
-
 
116
; RFC 1323                              ; the order of next 4 elements may not change
-
 
117
 
-
 
118
        SND_SCALE               db ?
-
 
119
        RCV_SCALE               db ?
-
 
120
        requested_s_scale       db ?
-
 
121
        request_r_scale         db ?
-
 
122
 
-
 
123
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
-
 
124
        ts_recent_age           dd ?
-
 
125
        last_ack_sent           dd ?
-
 
126
 
-
 
127
 
-
 
128
;-------
-
 
129
; Timers
-
 
130
        timer_retransmission    dd ? ; rexmt
54
        SEG_LEN        dd ? ; segment length
131
        timer_persist           dd ?
-
 
132
        timer_keepalive         dd ? ; keepalive/syn timeout
-
 
133
        timer_timed_wait        dd ? ; also used as 2msl timer
-
 
134
 
-
 
135
; extra
-
 
136
 
-
 
137
        ts_ecr                  dd ? ; timestamp echo reply
-
 
138
        ts_val                  dd ?
-
 
139
 
-
 
140
        seg_next                dd ? ; re-assembly queue
-
 
141
 
-
 
142
        temp_bits               db ?
-
 
143
                                rb 3 ; align
-
 
144
 
-
 
145
ends
-
 
146
 
-
 
147
struct  UDP_SOCKET              IP_SOCKET
-
 
148
 
-
 
149
        LocalPort               dw ? ; network byte order
-
 
150
        RemotePort              dw ? ; network byte order
-
 
151
        firstpacket             db ?
-
 
152
 
-
 
153
ends
-
 
154
 
-
 
155
 
-
 
156
struct  ICMP_SOCKET             IP_SOCKET
-
 
157
 
-
 
158
        Identifier              dw ?
-
 
159
 
-
 
160
ends
-
 
161
 
-
 
162
 
55
        SEG_WND        dd ? ; segment window
163
struct  RING_BUFFER
-
 
164
 
-
 
165
        mutex                   MUTEX
-
 
166
        start_ptr               dd ? ; Pointer to start of buffer
-
 
167
        end_ptr                 dd ? ; pointer to end of buffer
56
        wndsizeTimer   dd ? ; window size timer
168
        read_ptr                dd ? ; Read pointer
-
 
169
        write_ptr               dd ? ; Write pointer
-
 
170
        size                    dd ? ; Number of bytes buffered
-
 
171
 
-
 
172
ends
-
 
173
 
-
 
174
struct  STREAM_SOCKET           TCP_SOCKET
-
 
175
 
-
 
176
        rcv                     RING_BUFFER
-
 
177
        snd                     RING_BUFFER
-
 
178
 
-
 
179
ends
-
 
180
 
-
 
181
struct  socket_queue_entry
-
 
182
 
-
 
183
        data_ptr                dd ?
-
 
184
        buf_ptr                 dd ?
57
        mutex          MUTEX ; lock mutex
185
        data_size               dd ?
Line 58... Line -...
58
        rxData         dd ? ; receive data buffer here
-
 
59
ends
-
 
60
 
-
 
61
; TCP opening modes
-
 
62
SOCKET_PASSIVE = 0
-
 
63
SOCKET_ACTIVE  = 1
-
 
64
 
-
 
Line 65... Line 186...
65
; socket types
186
 
-
 
187
ends
-
 
188
 
-
 
189
 
-
 
190
SOCKETBUFFSIZE          = 4096     ; in bytes
-
 
191
 
66
SOCK_STREAM = 1
192
SOCKET_QUEUE_SIZE       = 10       ; maximum number of incoming packets queued for 1 socket
-
 
193
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
67
SOCK_DGRAM  = 2
194
SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
-
 
195
 
68
 
196
uglobal
69
; pointer to bitmap of free ports (1=free, 0=used)
197
        net_sockets     rd 4
Line 70... Line -...
70
uglobal
-
 
71
align 4
-
 
72
network_free_ports      dd      ?
-
 
73
endg
-
 
Line 74... Line 198...
74
 
198
        last_socket_num dd ?
75
iglobal
-
 
76
align 4
-
 
77
network_free_hint       dd      1024/8
199
        last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
78
endg
200
        last_TCP_port   dw ? ;
79
 
201
endg
80
;; Allocate memory for socket data and put new socket into the list
-
 
81
; Newly created socket is initialized with calling PID and number and
-
 
82
; put into beginning of list (which is a fastest way).
-
 
83
;
202
 
84
; @return socket structure address in EAX
-
 
85
;;
203
 
Line 86... Line -...
86
proc net_socket_alloc stdcall uses ebx ecx edx edi
-
 
87
        stdcall kernel_alloc, SOCKETBUFFSIZE
-
 
88
        DEBUGF  1, "K : net_socket_alloc (0x%x)\n", eax
-
 
89
        ; check if we can allocate needed amount of memory
-
 
90
        or      eax, eax
-
 
91
        jz      .exit
204
;-----------------------------------------------------------------
-
 
205
;
-
 
206
; SOCKET_init
92
 
207
;
-
 
208
;-----------------------------------------------------------------
-
 
209
macro   SOCKET_init {
-
 
210
 
-
 
211
        xor     eax, eax
-
 
212
        mov     edi, net_sockets
-
 
213
        mov     ecx, 5
-
 
214
        rep     stosd
-
 
215
 
-
 
216
       @@:
-
 
217
        pseudo_random eax
-
 
218
        cmp     ax, MIN_EPHEMERAL_PORT
-
 
219
        jb      @r
-
 
220
        cmp     ax, MAX_EPHEMERAL_PORT
-
 
221
        ja      @r
-
 
222
        xchg    al, ah
-
 
223
        mov     [last_UDP_port], ax
-
 
224
 
-
 
225
       @@:
-
 
226
        pseudo_random eax
-
 
227
        cmp     ax, MIN_EPHEMERAL_PORT
-
 
228
        jb      @r
-
 
229
        cmp     ax, MAX_EPHEMERAL_PORT
-
 
230
        ja      @r
-
 
231
        xchg    al, ah
-
 
232
        mov     [last_TCP_port], ax
-
 
233
 
-
 
234
}
-
 
235
 
-
 
236
;-----------------------------------------------------------------
-
 
237
;
-
 
238
; Socket API (function 74)
-
 
239
;
-
 
240
;-----------------------------------------------------------------
-
 
241
align 4
-
 
242
sys_socket:
-
 
243
 
-
 
244
        cmp     ebx, 255
-
 
245
        jz      SOCKET_debug
-
 
246
 
-
 
247
        cmp     ebx, .number
-
 
248
        ja      s_error
-
 
249
        jmp     dword [.table + 4*ebx]
-
 
250
 
-
 
251
  .table:
-
 
252
        dd      SOCKET_open     ; 0
-
 
253
        dd      SOCKET_close    ; 1
-
 
254
        dd      SOCKET_bind     ; 2
-
 
255
        dd      SOCKET_listen   ; 3
-
 
256
        dd      SOCKET_connect  ; 4
-
 
257
        dd      SOCKET_accept   ; 5
-
 
258
        dd      SOCKET_send     ; 6
-
 
259
        dd      SOCKET_receive  ; 7
-
 
260
        dd      SOCKET_set_opt  ; 8
-
 
261
        dd      SOCKET_get_opt  ; 9
-
 
262
        dd      SOCKET_pair     ; 10
-
 
263
  .number = ($ - .table) / 4 - 1
-
 
264
 
-
 
265
s_error:
-
 
266
        DEBUGF  2,"SOCKET: error\n"
-
 
267
        mov     dword [esp+32], -1
-
 
268
 
-
 
269
        ret
-
 
270
 
-
 
271
;-----------------------------------------------------------------
-
 
272
;
-
 
273
; SOCKET_open
-
 
274
;
-
 
275
;  IN:  domain in ecx
-
 
276
;       type in edx
-
 
277
;       protocol in esi
-
 
278
;  OUT: eax is socket num, -1 on error
-
 
279
;
-
 
280
;-----------------------------------------------------------------
-
 
281
align 4
-
 
282
SOCKET_open:
-
 
283
 
-
 
284
        DEBUGF  2,"SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
-
 
285
 
-
 
286
        push    ecx edx esi
-
 
287
        call    SOCKET_alloc
-
 
288
        pop     esi edx ecx
-
 
289
        jz      s_error
-
 
290
 
-
 
291
        mov     [esp+32], edi                   ; return socketnumber
-
 
292
        DEBUGF  2,"socknum=%u\n", edi
-
 
293
 
-
 
294
;        push    edx
-
 
295
;        and     edx, SO_NONBLOCK
-
 
296
        or      [eax + SOCKET.options], SO_NONBLOCK ;edx
-
 
297
;        pop     edx
-
 
298
;        and     edx, not SO_NONBLOCK
-
 
299
 
-
 
300
        mov     [eax + SOCKET.Domain], ecx
-
 
301
        mov     [eax + SOCKET.Type], edx
-
 
302
        mov     [eax + SOCKET.Protocol], esi
-
 
303
 
-
 
304
        cmp     ecx, AF_INET4
-
 
305
        jne     .no_inet4
-
 
306
 
-
 
307
        cmp     edx, SOCK_DGRAM
-
 
308
        je      .udp
-
 
309
 
-
 
310
        cmp     edx, SOCK_STREAM
-
 
311
        je      .tcp
-
 
312
 
-
 
313
        cmp     edx, SOCK_RAW
-
 
314
        je      .raw
-
 
315
 
-
 
316
  .no_inet4:
-
 
317
        cmp     ecx, AF_PPP
-
 
318
        jne     .no_ppp
-
 
319
 
-
 
320
        cmp     esi, PPP_PROTO_ETHERNET
-
 
321
        je      .pppoe
-
 
322
 
-
 
323
  .no_ppp:
-
 
324
        DEBUGF  2,"Unknown socket family/protocol\n"
-
 
325
        ret
-
 
326
 
-
 
327
align 4
-
 
328
  .raw:
-
 
329
        test    esi, esi       ; IP_PROTO_IP
-
 
330
        jz      .ip
-
 
331
 
-
 
332
        cmp     esi, IP_PROTO_ICMP
-
 
333
        je      .icmp
-
 
334
 
-
 
335
        cmp     esi, IP_PROTO_UDP
-
 
336
        je      .udp
-
 
337
 
-
 
338
        cmp     esi, IP_PROTO_TCP
-
 
339
        je      .tcp
-
 
340
 
-
 
341
        ret
-
 
342
 
-
 
343
align 4
-
 
344
  .udp:
-
 
345
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
-
 
346
        mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
-
 
347
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
-
 
348
        ret
-
 
349
 
-
 
350
align 4
-
 
351
  .tcp:
-
 
352
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
-
 
353
        mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
-
 
354
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
-
 
355
 
-
 
356
        TCP_init_socket eax
-
 
357
        ret
-
 
358
 
-
 
359
 
-
 
360
align 4
-
 
361
  .ip:
-
 
362
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
-
 
363
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
-
 
364
        ret
-
 
365
 
-
 
366
 
-
 
367
align 4
-
 
368
  .icmp:
-
 
369
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
93
        ; zero-initialize allocated memory
370
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
Line -... Line 371...
-
 
371
        ret
-
 
372
 
-
 
373
align 4
-
 
374
  .pppoe:
-
 
375
        push    eax
-
 
376
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
-
 
377
        pop     eax
-
 
378
 
-
 
379
        mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
-
 
380
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
-
 
381
        ret
-
 
382
 
-
 
383
 
-
 
384
;-----------------------------------------------------------------
-
 
385
;
-
 
386
; SOCKET_bind
-
 
387
;
-
 
388
;  IN:  socket number in ecx
-
 
389
;       pointer to sockaddr struct in edx
-
 
390
;       length of that struct in esi
-
 
391
;  OUT: 0 on success
-
 
392
;
-
 
393
;-----------------------------------------------------------------
-
 
394
align 4
-
 
395
SOCKET_bind:
-
 
396
 
-
 
397
        DEBUGF  2,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
-
 
398
 
-
 
399
        call    SOCKET_num_to_ptr
-
 
400
        jz      s_error
-
 
401
 
-
 
402
        cmp     esi, 2
-
 
403
        jb      s_error
-
 
404
 
-
 
405
        cmp     word [edx], AF_INET4
-
 
406
        je      .af_inet4
-
 
407
 
-
 
408
        cmp     word [edx], AF_LOCAL
-
 
409
        je      .af_local
-
 
410
 
-
 
411
        jmp     s_error
-
 
412
 
-
 
413
  .af_local:
-
 
414
        ; TODO: write code here
-
 
415
 
-
 
416
        mov     dword [esp+32], 0
-
 
417
        ret
-
 
418
 
-
 
419
  .af_inet4:
-
 
420
 
-
 
421
        cmp     esi, 6
-
 
422
        jb      s_error
-
 
423
 
-
 
424
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
-
 
425
        je      .udp
-
 
426
 
-
 
427
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
-
 
428
        je      .tcp
-
 
429
 
-
 
430
        jmp     s_error
-
 
431
 
-
 
432
  .tcp:
-
 
433
  .udp:
-
 
434
 
-
 
435
        mov     ebx, [edx + 4]                  ; First, fill in the IP
-
 
436
        test    ebx, ebx                        ; If IP is 0, use default
-
 
437
        jnz     @f
-
 
438
        mov     ebx, [NET_DEFAULT]
-
 
439
        mov     ebx, [IP_LIST + 4*ebx]
-
 
440
       @@:
-
 
441
        mov     [eax + IP_SOCKET.LocalIP], ebx
-
 
442
 
-
 
443
        mov     bx, [edx + 2]                   ; Now fill in the local port if it's still available
-
 
444
        call    SOCKET_check_port
-
 
445
        jz      s_error                         ; ZF is set by socket_check_port, on error
-
 
446
 
-
 
447
        DEBUGF  1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\
-
 
448
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
-
 
449
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
-
 
450
 
-
 
451
        mov     dword [esp+32], 0
-
 
452
        ret
-
 
453
 
-
 
454
 
-
 
455
 
-
 
456
 
-
 
457
;-----------------------------------------------------------------
-
 
458
;
-
 
459
; SOCKET_connect
-
 
460
;
-
 
461
;  IN:  socket number in ecx
-
 
462
;       pointer to sockaddr struct in edx
-
 
463
;       length of that struct in esi
-
 
464
;  OUT: 0 on success
-
 
465
;
-
 
466
;-----------------------------------------------------------------
94
        push    eax
467
align 4
-
 
468
SOCKET_connect:
-
 
469
 
-
 
470
        DEBUGF  2,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
-
 
471
 
-
 
472
        call    SOCKET_num_to_ptr
-
 
473
        jz      s_error
-
 
474
 
-
 
475
        cmp     esi, 8
-
 
476
        jb      s_error
-
 
477
 
-
 
478
        cmp     word [edx], AF_INET4
-
 
479
        je      .af_inet4
-
 
480
 
-
 
481
        jmp     s_error
-
 
482
 
-
 
483
  .af_inet4:
-
 
484
        cmp     [eax + IP_SOCKET.LocalIP], 0
-
 
485
        jne     @f
-
 
486
        push    [IP_LIST]                               ; FIXME
-
 
487
        pop     [eax + IP_SOCKET.LocalIP]
-
 
488
       @@:
-
 
489
 
-
 
490
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
-
 
491
        je      .udp
-
 
492
 
-
 
493
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
-
 
494
        je      .tcp
-
 
495
 
-
 
496
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
-
 
497
        je      .ip
-
 
498
 
95
        mov     edi, eax
499
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
96
        mov     ecx, SOCKETBUFFSIZE / 4
500
        je      .ip
-
 
501
 
-
 
502
        jmp     s_error
-
 
503
 
-
 
504
align 4
-
 
505
  .udp:
-
 
506
        pusha
-
 
507
        lea     ecx, [eax + SOCKET.mutex]
-
 
508
        call    mutex_lock
-
 
509
        popa
-
 
510
 
-
 
511
        pushw   [edx + 2]
-
 
512
        pop     [eax + UDP_SOCKET.RemotePort]
-
 
513
 
-
 
514
        pushd   [edx + 4]
-
 
515
        pop     [eax + IP_SOCKET.RemoteIP]
-
 
516
 
-
 
517
        cmp     [eax + UDP_SOCKET.LocalPort], 0
-
 
518
        jne     @f
-
 
519
        call    SOCKET_find_port
-
 
520
       @@:
-
 
521
 
-
 
522
        mov     [eax + UDP_SOCKET.firstpacket], 0
-
 
523
 
-
 
524
        push    eax
-
 
525
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
-
 
526
        pop     eax
-
 
527
 
-
 
528
        lea     ecx, [eax + SOCKET.mutex]
-
 
529
        call    mutex_unlock
-
 
530
 
-
 
531
        mov     dword [esp+32], 0
-
 
532
        ret
-
 
533
 
-
 
534
align 4
-
 
535
  .tcp:
-
 
536
        pusha
-
 
537
        lea     ecx, [eax + SOCKET.mutex]
-
 
538
        call    mutex_lock
-
 
539
        popa
-
 
540
 
-
 
541
        pushw   [edx + 2]
-
 
542
        pop     [eax + TCP_SOCKET.RemotePort]
-
 
543
 
-
 
544
        pushd   [edx + 4]
-
 
545
        pop     [eax + IP_SOCKET.RemoteIP]
-
 
546
 
-
 
547
        cmp     [eax + TCP_SOCKET.LocalPort], 0
-
 
548
        jne     @f
-
 
549
        call    SOCKET_find_port
-
 
550
       @@:
-
 
551
 
-
 
552
        mov     [eax + TCP_SOCKET.timer_persist], 0
-
 
553
        mov     [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
-
 
554
 
-
 
555
        push    [TCP_sequence_num]
-
 
556
        add     [TCP_sequence_num], 6400
-
 
557
        pop     [eax + TCP_SOCKET.ISS]
-
 
558
        mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
-
 
559
 
-
 
560
 
-
 
561
        TCP_sendseqinit eax
-
 
562
 
-
 
563
;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
-
 
564
 
-
 
565
        mov     ebx, eax
-
 
566
 
-
 
567
        lea     eax, [ebx + STREAM_SOCKET.snd]
-
 
568
        call    SOCKET_ring_create
-
 
569
 
97
        cld
570
        lea     eax, [ebx + STREAM_SOCKET.rcv]
-
 
571
        call    SOCKET_ring_create
Line 98... Line 572...
98
        xor     eax, eax
572
 
-
 
573
        pusha
99
        rep stosd
574
        lea     ecx, [ebx + SOCKET.mutex]
-
 
575
        call    mutex_unlock
-
 
576
        popa
-
 
577
 
-
 
578
        mov     eax, ebx
-
 
579
        call    TCP_output
-
 
580
 
-
 
581
;;; TODO: wait for successfull connection if blocking socket
-
 
582
 
-
 
583
        mov     dword [esp+32], 0
-
 
584
        ret
100
        pop     eax
585
 
-
 
586
align 4
-
 
587
  .ip:
-
 
588
        pusha
-
 
589
        lea     ecx, [eax + SOCKET.mutex]
-
 
590
        call    mutex_lock
-
 
591
        popa
-
 
592
 
-
 
593
        pushd   [edx + 4]
-
 
594
        pop     [eax + IP_SOCKET.RemoteIP]
-
 
595
 
-
 
596
        push    eax
-
 
597
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
-
 
598
        pop     eax
-
 
599
 
-
 
600
        lea     ecx, [eax + SOCKET.mutex]
-
 
601
        call    mutex_unlock
-
 
602
 
-
 
603
        mov     dword [esp+32], 0
-
 
604
        ret
-
 
605
 
-
 
606
 
-
 
607
;-----------------------------------------------------------------
-
 
608
;
-
 
609
; SOCKET_listen
-
 
610
;
-
 
611
;  IN:  socket number in ecx
-
 
612
;       backlog in edx
-
 
613
;  OUT: eax is socket num, -1 on error
-
 
614
;
-
 
615
;-----------------------------------------------------------------
-
 
616
align 4
-
 
617
SOCKET_listen:
-
 
618
 
-
 
619
        DEBUGF  2,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
-
 
620
 
-
 
621
        call    SOCKET_num_to_ptr
-
 
622
        jz      s_error
-
 
623
 
101
 
624
        cmp     [eax + SOCKET.Domain], AF_INET4
-
 
625
        jne     s_error
-
 
626
 
-
 
627
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
-
 
628
        jne     s_error
-
 
629
 
-
 
630
        cmp     [eax + TCP_SOCKET.LocalPort], 0
-
 
631
        je      s_error
-
 
632
 
-
 
633
        cmp     [eax + IP_SOCKET.LocalIP], 0
-
 
634
        jne     @f
102
        mov     ebx, eax
635
        push    [IP_LIST]
-
 
636
        pop     [eax + IP_SOCKET.LocalIP]
-
 
637
       @@:
-
 
638
 
-
 
639
        cmp     edx, MAX_backlog
-
 
640
        jbe     @f
-
 
641
        mov     edx, MAX_backlog
103
        lea     ecx, [eax+SOCKET.mutex]
642
       @@:
-
 
643
 
-
 
644
        mov     [eax + SOCKET.backlog], dx
-
 
645
        or      [eax + SOCKET.options], SO_ACCEPTCON
-
 
646
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
-
 
647
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
-
 
648
 
-
 
649
        push    eax
-
 
650
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
-
 
651
        pop     eax
-
 
652
 
-
 
653
        mov     dword [esp+32], 0
-
 
654
 
-
 
655
        ret
-
 
656
 
-
 
657
 
-
 
658
;-----------------------------------------------------------------
-
 
659
;
-
 
660
; SOCKET_accept
-
 
661
;
-
 
662
;  IN:  socket number in ecx
-
 
663
;       addr in edx
-
 
664
;       addrlen in esi
-
 
665
;  OUT: eax is socket num, -1 on error
-
 
666
;
-
 
667
;-----------------------------------------------------------------
-
 
668
align 4
-
 
669
SOCKET_accept:
-
 
670
 
-
 
671
        DEBUGF  2,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
-
 
672
 
-
 
673
        call    SOCKET_num_to_ptr
-
 
674
        jz      s_error
-
 
675
 
-
 
676
        test    [eax + SOCKET.options], SO_ACCEPTCON
-
 
677
        jz      s_error
-
 
678
 
-
 
679
        cmp     [eax + SOCKET.Domain], AF_INET4
-
 
680
        jne     s_error
-
 
681
 
-
 
682
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
-
 
683
        jne     s_error
-
 
684
 
104
        call    mutex_init
685
  .loop:
-
 
686
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
-
 
687
 
-
 
688
; Ok, we got a socket ptr
-
 
689
        mov     eax, [esi]
-
 
690
 
105
        mov     eax, ebx
691
; Change thread ID to that of the current thread
-
 
692
        mov     ebx, [TASK_BASE]
-
 
693
        mov     ebx, [ebx + TASKDATA.pid]
-
 
694
        mov     [eax + SOCKET.TID], ebx
-
 
695
 
-
 
696
; Convert it to a socket number
-
 
697
        call    SOCKET_ptr_to_num
-
 
698
        jz      s_error
-
 
699
; and return it to caller
-
 
700
        mov     [esp+32], eax
-
 
701
        ret
-
 
702
 
-
 
703
  .block:
-
 
704
        test    [eax + SOCKET.options], SO_NONBLOCK
-
 
705
        jnz     s_error
-
 
706
 
-
 
707
        call    SOCKET_block
-
 
708
        jmp     .loop
-
 
709
 
-
 
710
;-----------------------------------------------------------------
-
 
711
;
-
 
712
; SOCKET_close
-
 
713
;
-
 
714
;  IN:  socket number in ecx
-
 
715
;  OUT: eax is socket num, -1 on error
-
 
716
;
-
 
717
;-----------------------------------------------------------------
-
 
718
align 4
-
 
719
SOCKET_close:
-
 
720
 
-
 
721
        DEBUGF  2,"SOCKET_close: socknum=%u\n", ecx
-
 
722
 
106
 
723
        call    SOCKET_num_to_ptr
-
 
724
        jz      s_error
-
 
725
 
-
 
726
        mov     dword [esp+32], 0                               ; The socket exists, so we will succeed in closing it.
-
 
727
 
-
 
728
  .socket:
-
 
729
        or      [eax + SOCKET.options], SO_NONBLOCK             ; Mark the socket as non blocking, we dont want it to block any longer!
-
 
730
 
-
 
731
        test    [eax + SOCKET.state], SS_BLOCKED                ; Is the socket still in blocked state?
-
 
732
        jz      @f
-
 
733
        call    SOCKET_notify.unblock                           ; Unblock it.
-
 
734
  @@:
-
 
735
 
-
 
736
        cmp     [eax + SOCKET.Domain], AF_INET4
-
 
737
        jne     .free
-
 
738
 
-
 
739
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
-
 
740
        je      .tcp
-
 
741
 
-
 
742
  .free:
-
 
743
        call    SOCKET_free
-
 
744
        ret
-
 
745
 
-
 
746
  .tcp:
-
 
747
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
-
 
748
        jb      .free
-
 
749
 
-
 
750
        call    TCP_usrclosed
-
 
751
        call    TCP_output      ;;;; Fixme: is this nescessary??
-
 
752
 
-
 
753
        ret
-
 
754
 
-
 
755
 
-
 
756
;-----------------------------------------------------------------
-
 
757
;
-
 
758
; SOCKET_receive
-
 
759
;
-
 
760
;  IN:  socket number in ecx
-
 
761
;       addr to buffer in edx
-
 
762
;       length of buffer in esi
-
 
763
;       flags in edi
-
 
764
;  OUT: eax is number of bytes copied, -1 on error
-
 
765
;
107
        ; add socket to the list by changing pointers
766
;-----------------------------------------------------------------
-
 
767
align 4
-
 
768
SOCKET_receive:
-
 
769
 
-
 
770
        DEBUGF  2,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
-
 
771
 
-
 
772
        call    SOCKET_num_to_ptr
-
 
773
        jz      s_error
-
 
774
 
-
 
775
        jmp     [eax + SOCKET.rcv_proc]
-
 
776
 
-
 
777
 
-
 
778
align 4
-
 
779
SOCKET_receive_dgram:
-
 
780
 
-
 
781
        DEBUGF  1,"SOCKET_receive: DGRAM\n"
-
 
782
 
-
 
783
        mov     ebx, esi
-
 
784
        mov     edi, edx                                        ; addr to buffer
-
 
785
 
-
 
786
  .loop:
-
 
787
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .block      ; destroys esi and ecx
-
 
788
 
-
 
789
        mov     ecx, [esi + socket_queue_entry.data_size]
-
 
790
        DEBUGF  1,"SOCKET_receive: %u bytes data\n", ecx
-
 
791
 
-
 
792
        cmp     ecx, ebx
-
 
793
        ja      .too_small
-
 
794
 
-
 
795
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
-
 
796
        mov     esi, [esi + socket_queue_entry.data_ptr]
-
 
797
        DEBUGF  1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
-
 
798
        mov     [esp+32+4], ecx                                 ; return number of bytes copied
-
 
799
 
-
 
800
; copy the data
-
 
801
        shr     ecx, 1
-
 
802
        jnc     .nb
-
 
803
        movsb
Line -... Line 804...
-
 
804
  .nb:
-
 
805
        shr     ecx, 1
-
 
806
        jnc     .nw
-
 
807
        movsw
-
 
808
  .nw:
-
 
809
        test    ecx, ecx
-
 
810
        jz      .nd
-
 
811
        rep     movsd
-
 
812
  .nd:
-
 
813
 
-
 
814
        call    kernel_free                                     ; remove the packet
-
 
815
        ret
-
 
816
 
-
 
817
  .too_small:
-
 
818
 
-
 
819
        DEBUGF  2,"SOCKET_receive: Buffer too small\n"
-
 
820
        jmp     s_error
-
 
821
 
-
 
822
  .block:
-
 
823
        test    [eax + SOCKET.options], SO_NONBLOCK
-
 
824
        jnz     s_error
-
 
825
 
-
 
826
        call    SOCKET_block
108
        mov     ebx, net_sockets
827
        jmp     .loop
109
        push    [ebx + SOCKET.NextPtr]
828
 
110
        mov     [ebx + SOCKET.NextPtr], eax
829
 
111
        mov     [eax + SOCKET.PrevPtr], ebx
830
align 4
-
 
831
SOCKET_receive_local:
-
 
832
 
Line 112... Line -...
112
        pop     ebx
-
 
113
        mov     [eax + SOCKET.NextPtr], ebx
-
 
114
        or      ebx, ebx
833
        ; does this socket have a PID yet?
115
        jz      @f
-
 
116
        mov     [ebx + SOCKET.PrevPtr], eax
-
 
-
 
834
        cmp     [eax + SOCKET.PID], 0
117
 
835
        jne     @f
118
    @@: ; set socket owner PID to the one of calling process
836
 
119
        mov     ebx, [TASK_BASE]
-
 
120
        mov     ebx, [ebx + TASKDATA.pid]
-
 
121
        mov     [eax + SOCKET.PID], ebx
-
 
122
 
-
 
123
        ; find first free socket number and use it
-
 
124
        ;mov     edx, ebx
-
 
125
        mov     ebx, net_sockets
-
 
126
        xor     ecx, ecx
-
 
127
  .next_socket_number:
-
 
Line 128... Line -...
128
        inc     ecx
-
 
129
  .next_socket:
837
        ; Change PID to that of current process
Line -... Line 838...
-
 
838
        mov     ebx, [TASK_BASE]
-
 
839
        mov     ebx, [ebx + TASKDATA.pid]
-
 
840
        mov     [eax + SOCKET.PID], ebx
-
 
841
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
-
 
842
      @@:
-
 
843
 
-
 
844
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
130
        mov     ebx, [ebx + SOCKET.NextPtr]
845
 
-
 
846
align 4
-
 
847
SOCKET_receive_stream:
-
 
848
 
-
 
849
        DEBUGF  1,"SOCKET_receive: STREAM\n"
-
 
850
 
-
 
851
        mov     ebx, edi
-
 
852
        mov     ecx, esi
-
 
853
        mov     edi, edx
-
 
854
        xor     edx, edx
-
 
855
 
-
 
856
        test    ebx, MSG_DONTWAIT
131
        or      ebx, ebx
857
        jnz     .dontwait
132
        jz      .last_socket_number
-
 
Line -... Line 858...
-
 
858
  .loop:
-
 
859
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
-
 
860
        je      .block
-
 
861
  .dontwait:
-
 
862
        test    ebx, MSG_PEEK
-
 
863
        jnz     .peek
133
        cmp     [ebx + SOCKET.Number], ecx
864
 
-
 
865
        add     eax, STREAM_SOCKET.rcv
-
 
866
        call    SOCKET_ring_read
-
 
867
        call    SOCKET_ring_free
-
 
868
 
-
 
869
        mov     [esp+32], ecx                                   ; return number of bytes copied
-
 
870
        ret
-
 
871
 
-
 
872
  .peek:
-
 
873
        mov     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
-
 
874
        mov     [esp+32], ecx                                   ; return number of bytes available
-
 
875
        ret
-
 
876
 
134
        jne     .next_socket
877
  .block:
135
        ;cmp     [ebx + SOCKET.PID], edx
878
        test    [eax + SOCKET.options], SO_NONBLOCK
-
 
879
        jnz     .return0
136
        ;jne     .next_socket
880
 
137
        mov     ebx, net_sockets
881
        call    SOCKET_block
138
        jmp     .next_socket_number
882
        jmp     .loop
139
 
883
 
140
  .last_socket_number:
-
 
141
        mov     [eax + SOCKET.Number], ecx
884
  .return0:
142
 
885
        xor     ecx, ecx
-
 
886
        mov     [esp+32], ecx
-
 
887
        ret
-
 
888
 
-
 
889
 
Line 143... Line 890...
143
  .exit:
890
;-----------------------------------------------------------------
-
 
891
;
-
 
892
; SOCKET_send
-
 
893
;
-
 
894
;
144
        ret
895
;  IN:  socket number in ecx
145
endp
896
;       pointer to data in edx
-
 
897
;       datalength in esi
146
 
898
;       flags in edi
-
 
899
;  OUT: -1 on error
-
 
900
;
-
 
901
;-----------------------------------------------------------------
147
;; Free socket data memory and pop socket off the list
902
align 4
-
 
903
SOCKET_send:
148
;
904
 
-
 
905
        DEBUGF  2,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
149
; @param sockAddr is a socket structure address
906
 
150
;;
907
        call    SOCKET_num_to_ptr
151
proc net_socket_free stdcall uses ebx ecx edx, sockAddr:DWORD
908
        jz      s_error
152
        mov     eax, [sockAddr]
909
 
153
        DEBUGF  1, "K : net_socket_free (0x%x)\n", eax
910
        mov     ecx, esi
-
 
911
        mov     esi, edx
-
 
912
 
-
 
913
        jmp     [eax + SOCKET.snd_proc]
-
 
914
 
-
 
915
 
154
        ; check if we got something similar to socket structure address
916
align 4
Line 155... Line -...
155
        or      eax, eax
-
 
156
        jz      .error
-
 
157
 
-
 
158
        ; make sure sockAddr is one of the socket addresses in the list
917
SOCKET_send_udp:
159
        mov     ebx, net_sockets
918
 
160
        ;mov     ecx, [TASK_BASE]
919
        DEBUGF  1,"SOCKET_send: UDP\n"
161
        ;mov     ecx, [ecx + TASKDATA.pid]
-
 
162
  .next_socket:
920
 
-
 
921
        mov     [esp+32], ecx
-
 
922
        call    UDP_output
-
 
923
        cmp     eax, -1
-
 
924
        je      s_error
-
 
925
        ret
-
 
926
 
-
 
927
 
-
 
928
align 4
-
 
929
SOCKET_send_tcp:
-
 
930
 
-
 
931
        DEBUGF  1,"SOCKET_send: TCP\n"
-
 
932
 
-
 
933
        push    eax
-
 
934
        add     eax, STREAM_SOCKET.snd
-
 
935
        call    SOCKET_ring_write
-
 
936
        pop     eax
-
 
937
 
-
 
938
        mov     [esp+32], ecx
-
 
939
 
-
 
940
        call    TCP_output
-
 
941
        ret
-
 
942
 
-
 
943
 
-
 
944
align 4
-
 
945
SOCKET_send_ip:
-
 
946
 
-
 
947
        DEBUGF  1,"SOCKET_send: IPv4\n"
-
 
948
 
-
 
949
        mov     [esp+32], ecx
-
 
950
        call    IPv4_output_raw
-
 
951
        cmp     eax, -1
-
 
952
        je      s_error
-
 
953
        ret
-
 
954
 
-
 
955
 
-
 
956
align 4
-
 
957
SOCKET_send_icmp:
-
 
958
 
-
 
959
        DEBUGF  1,"SOCKET_send: ICMP\n"
-
 
960
 
-
 
961
        mov     [esp+32], ecx
-
 
962
        call    ICMP_output_raw
-
 
963
        cmp     eax, -1
-
 
964
        je      s_error
-
 
965
        ret
-
 
966
 
-
 
967
 
-
 
968
align 4
-
 
969
SOCKET_send_pppoe:
-
 
970
 
-
 
971
        DEBUGF  1,"SOCKET_send: PPPoE\n"
-
 
972
 
-
 
973
        mov     [esp+32], ecx
163
        mov     ebx, [ebx + SOCKET.NextPtr]
974
        mov     ebx, [eax + SOCKET.device]
-
 
975
 
164
        or      ebx, ebx
976
        call    PPPoE_discovery_output
-
 
977
        cmp     eax, -1
-
 
978
        je      s_error
-
 
979
        ret
-
 
980
 
-
 
981
 
-
 
982
 
-
 
983
align 4
-
 
984
SOCKET_send_local:
-
 
985
 
-
 
986
        ; does this socket have a PID yet?
-
 
987
        cmp     [eax + SOCKET.PID], 0
165
        jz      .error
988
        jne     @f
-
 
989
 
-
 
990
        ; Change PID to that of current process
-
 
991
        mov     ebx, [TASK_BASE]
-
 
992
        mov     ebx, [ebx + TASKDATA.pid]
-
 
993
        mov     [eax + SOCKET.PID], ebx
-
 
994
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
-
 
995
      @@:
-
 
996
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local_
-
 
997
 
-
 
998
align 4
-
 
999
SOCKET_send_local_:
-
 
1000
 
-
 
1001
        DEBUGF  1,"SOCKET_send: LOCAL\n"
-
 
1002
 
-
 
1003
        ; get the other side's socket and check if it still exists
-
 
1004
        mov     eax, [eax + SOCKET.device]
-
 
1005
        call    SOCKET_check
-
 
1006
        jz      s_error
-
 
1007
 
-
 
1008
        ; allright, shove in the data!
-
 
1009
        push    eax
-
 
1010
        add     eax, STREAM_SOCKET.rcv
-
 
1011
        call    SOCKET_ring_write
-
 
1012
        pop     eax
-
 
1013
 
-
 
1014
        ; return the number of written bytes (or errorcode) to application
-
 
1015
        mov     [esp+32], ecx
-
 
1016
 
-
 
1017
        ; and notify the other end
-
 
1018
        call    SOCKET_notify
-
 
1019
 
-
 
1020
        ret
-
 
1021
 
-
 
1022
 
-
 
1023
;-----------------------------------------------------------------
-
 
1024
;
-
 
1025
; SOCKET_get_options
-
 
1026
;
-
 
1027
;  IN:  ecx = socket number
-
 
1028
;       edx = pointer to the options:
-
 
1029
;               dd      level, optname, optval, optlen
-
 
1030
;  OUT: -1 on error
-
 
1031
;
-
 
1032
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
-
 
1033
; TODO: find best way to notify that send()'ed data were acknowledged
-
 
1034
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
-
 
1035
;
-
 
1036
;-----------------------------------------------------------------
-
 
1037
align 4
-
 
1038
SOCKET_get_opt:
-
 
1039
 
-
 
1040
        DEBUGF  2,"SOCKET_get_opt\n"
-
 
1041
 
-
 
1042
        call    SOCKET_num_to_ptr
-
 
1043
        jz      s_error
-
 
1044
 
-
 
1045
        cmp     dword [edx], IP_PROTO_TCP
-
 
1046
        jne     s_error
-
 
1047
        cmp     dword [edx+4], -2
-
 
1048
        je      @f
166
        cmp     ebx, eax
1049
        cmp     dword [edx+4], -3
-
 
1050
        jne     s_error
-
 
1051
@@:
167
        jne     .next_socket
1052
;        mov     eax, [edx+12]
168
        ;cmp     [ebx + SOCKET.PID], ecx
1053
;        test    eax, eax
169
        ;jne     .next_socket
1054
;        jz      .fail
-
 
1055
;        cmp     dword [eax], 4
-
 
1056
;        mov     dword [eax], 4
-
 
1057
;        jb      .fail
-
 
1058
;        stdcall net_socket_num_to_addr, ecx
-
 
1059
;        test    eax, eax
Line -... Line 1060...
-
 
1060
;        jz      .fail
-
 
1061
;        ; todo: check that eax is really TCP socket
-
 
1062
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
-
 
1063
;        cmp     dword [edx+4], -2
-
 
1064
;        jz      @f
-
 
1065
;        mov     ecx, [eax + TCP_SOCKET.state]
170
 
1066
@@:
-
 
1067
        mov     eax, [edx+8]
-
 
1068
        test    eax, eax
-
 
1069
        jz      @f
-
 
1070
        mov     [eax], ecx
-
 
1071
@@:
-
 
1072
        mov     dword [esp+32], 0
-
 
1073
        ret
-
 
1074
 
171
        ; okay, we found the correct one
1075
 
-
 
1076
 
-
 
1077
;-----------------------------------------------------------------
-
 
1078
;
-
 
1079
; SOCKET_set_options
-
 
1080
;
-
 
1081
;  IN:  ecx = socket number
-
 
1082
;       edx = pointer to the options:
-
 
1083
;               dd      level, optname, optlen, optval
-
 
1084
;  OUT: -1 on error
-
 
1085
;
-
 
1086
;-----------------------------------------------------------------
-
 
1087
align 4
-
 
1088
SOCKET_set_opt:
-
 
1089
 
-
 
1090
        DEBUGF  2,"SOCKET_set_opt\n"
-
 
1091
 
-
 
1092
        call    SOCKET_num_to_ptr
-
 
1093
        jz      s_error
-
 
1094
 
-
 
1095
        cmp     dword [edx], SOL_SOCKET
-
 
1096
        jne     s_error
-
 
1097
 
-
 
1098
        cmp     dword [edx+4], SO_BINDTODEVICE
-
 
1099
        je      .bind
-
 
1100
 
-
 
1101
        cmp     dword [edx+4], SO_BLOCK
-
 
1102
        je      .block
-
 
1103
 
-
 
1104
        jmp     s_error
172
        ; mark local port as unused
1105
 
Line 173... Line 1106...
173
        movzx   ebx, [eax + SOCKET.LocalPort]
1106
  .bind:
174
        push    eax
1107
        cmp     dword [edx+8], 0
-
 
1108
        je      .unbind
-
 
1109
 
175
        mov     eax, [network_free_ports]
1110
        movzx   edx, byte [edx + 9]
176
        xchg    bl, bh
-
 
Line 177... Line -...
177
        lock bts [eax], ebx
-
 
178
        pop     eax
-
 
179
        ; remove it from the list first, changing pointers
-
 
180
        mov     ebx, [eax + SOCKET.NextPtr]
1111
        cmp     edx, MAX_NET_DEVICES
181
        mov     eax, [eax + SOCKET.PrevPtr]
-
 
182
        mov     [eax + SOCKET.NextPtr], ebx
-
 
183
        or      ebx, ebx
-
 
184
        jz      @f
-
 
185
        mov     [ebx + SOCKET.PrevPtr], eax
-
 
186
 
1112
        ja      s_error
187
    @@: ; and finally free the memory structure used
-
 
188
        stdcall kernel_free, [sockAddr]
-
 
189
        ret
1113
 
Line 190... Line -...
190
 
-
 
191
  .error:
-
 
192
        DEBUGF  1, "K :   failed\n"
-
 
193
        ret
-
 
194
endp
-
 
195
 
-
 
196
;; Get socket structure address by its number
-
 
197
; Scan through sockets list to find the socket with specified number.
-
 
198
; This proc uses SOCKET.PID indirectly to check if socket is owned by
1114
        mov     edx, [NET_DRV_LIST + 4*edx]
199
; calling process.
-
 
200
;
-
 
201
; @param sockNum is a socket number
-
 
Line 202... Line 1115...
202
; @return socket structure address or 0 (not found) in EAX
1115
        test    edx, edx
203
;;
-
 
204
proc net_socket_num_to_addr stdcall uses ebx ecx, sockNum:DWORD
1116
        jz      s_error
Line 205... Line 1117...
205
        mov     eax, [sockNum]
1117
        mov     [eax + SOCKET.device], edx
206
        ; check if we got something similar to socket number
1118
 
-
 
1119
        DEBUGF  1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
-
 
1120
 
207
        or      eax, eax
1121
        mov     dword [esp+32], 0       ; success!
208
        jz      .error
-
 
Line 209... Line -...
209
 
-
 
210
        ; scan through sockets list
-
 
211
        mov     ebx, net_sockets
-
 
212
        ;mov     ecx, [TASK_BASE]
-
 
213
        ;mov     ecx, [ecx + TASKDATA.pid]
-
 
214
  .next_socket:
-
 
215
        mov     ebx, [ebx + SOCKET.NextPtr]
-
 
216
        or      ebx, ebx
-
 
217
        jz      .error
-
 
218
        cmp     [ebx + SOCKET.Number], eax
-
 
219
        jne     .next_socket
-
 
220
        ;cmp     [ebx + SOCKET.PID], ecx
-
 
221
        ;jne     .next_socket
-
 
Line -... Line 1122...
-
 
1122
        ret
-
 
1123
 
-
 
1124
  .unbind:
-
 
1125
        mov     [eax + SOCKET.device], 0
-
 
1126
 
-
 
1127
        mov     dword [esp+32], 0       ; success!
-
 
1128
        ret
-
 
1129
 
-
 
1130
  .block:
222
 
1131
        cmp     dword [edx+8], 0
-
 
1132
        je      .unblock
-
 
1133
 
-
 
1134
        and     [eax + SOCKET.options], not SO_NONBLOCK
-
 
1135
 
-
 
1136
        mov     dword [esp+32], 0       ; success!
-
 
1137
        ret
-
 
1138
 
223
        ; okay, we found the correct one
1139
  .unblock:
224
        mov     eax, ebx
1140
        or      [eax + SOCKET.options], SO_NONBLOCK
-
 
1141
 
-
 
1142
        mov     dword [esp+32], 0       ; success!
225
        ret
1143
        ret
226
 
1144
 
-
 
1145
 
-
 
1146
 
-
 
1147
;-----------------------------------------------------------------
227
  .error:
1148
;
228
        xor     eax, eax
1149
; SOCKET_pair
-
 
1150
;
-
 
1151
; Allocates a pair of linked LOCAL domain sockets
229
        ret
1152
;
-
 
1153
; IN: /
-
 
1154
; OUT: eax is socket1 num, -1 on error
-
 
1155
;      ebx is socket2 num
-
 
1156
;
-
 
1157
;-----------------------------------------------------------------
-
 
1158
align 4
-
 
1159
SOCKET_pair:
230
endp
1160
 
-
 
1161
        DEBUGF  2,"SOCKET_pair\n"
-
 
1162
 
231
 
1163
        call    SOCKET_alloc
232
;; Get socket number by its structure address
1164
        jz      s_error
-
 
1165
        mov     [esp+32], edi   ; application's eax
-
 
1166
 
-
 
1167
        mov     [eax + SOCKET.Domain], AF_LOCAL
-
 
1168
        mov     [eax + SOCKET.Type], SOCK_STREAM
-
 
1169
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
233
; Scan through sockets list to find the socket with specified address.
1170
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
-
 
1171
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
Line 234... Line -...
234
; This proc uses SOCKET.PID indirectly to check if socket is owned by
-
 
235
; calling process.
-
 
236
;
1172
        mov     [eax + SOCKET.PID], 0
Line 237... Line 1173...
237
; @param sockAddr is a socket structure address
1173
        mov     ebx, eax
238
; @return socket number (SOCKET.Number) or 0 (not found) in EAX
1174
 
-
 
1175
        call    SOCKET_alloc
-
 
1176
        jz      .error
-
 
1177
        mov     [esp+24], edi   ; application's ebx
-
 
1178
 
-
 
1179
        mov     [eax + SOCKET.Domain], AF_LOCAL
-
 
1180
        mov     [eax + SOCKET.Type], SOCK_STREAM
-
 
1181
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
-
 
1182
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
-
 
1183
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
-
 
1184
        mov     [eax + SOCKET.PID], 0
-
 
1185
 
-
 
1186
        ; Link the two sockets to eachother
-
 
1187
        mov     [eax + SOCKET.device], ebx
-
 
1188
        mov     [ebx + SOCKET.device], eax
-
 
1189
 
-
 
1190
        lea     eax, [eax + STREAM_SOCKET.rcv]
-
 
1191
        call    SOCKET_ring_create
-
 
1192
 
-
 
1193
        lea     eax, [ebx + STREAM_SOCKET.rcv]
-
 
1194
        call    SOCKET_ring_create
-
 
1195
        pop     eax
-
 
1196
 
-
 
1197
        ret
-
 
1198
 
-
 
1199
  .error:
-
 
1200
        mov     eax, ebx
-
 
1201
        call    SOCKET_free
-
 
1202
        jmp     s_error
-
 
1203
 
-
 
1204
 
-
 
1205
 
-
 
1206
;-----------------------------------------------------------------
-
 
1207
;
-
 
1208
; SOCKET_debug
239
;;
1209
;
240
proc net_socket_addr_to_num stdcall uses ebx ecx, sockAddr:DWORD
-
 
Line 241... Line -...
241
        mov     eax, [sockAddr]
-
 
242
        ; check if we got something similar to socket structure address
-
 
243
        or      eax, eax
-
 
244
        jz      .error
-
 
245
 
-
 
246
        ; scan through sockets list
-
 
247
        mov     ebx, net_sockets
-
 
248
        ;mov     ecx, [TASK_BASE]
-
 
249
        ;mov     ecx, [ecx + TASKDATA.pid]
-
 
250
  .next_socket:
-
 
251
        mov     ebx, [ebx + SOCKET.NextPtr]
-
 
252
        or      ebx, ebx
-
 
253
        jz      .error
-
 
254
        cmp     ebx, eax
-
 
255
        jne     .next_socket
1210
;  Copies socket variables to application buffer
256
        ;cmp     [ebx + SOCKET.PID], ecx
1211
;
257
        ;jne     .next_socket
-
 
258
 
-
 
259
        ; okay, we found the correct one
-
 
260
        mov     eax, [ebx + SOCKET.Number]
-
 
261
        ret
1212
;  IN:  ecx = socket number
262
 
-
 
263
  .error:
-
 
264
        xor     eax, eax
-
 
265
        ret
-
 
266
endp
-
 
267
 
-
 
268
;; [53.9] Check if local port is used by any socket in the system.
-
 
269
; Scan through sockets list, checking SOCKET.LocalPort.
-
 
270
; Useful when you want a to generate a unique local port number.
-
 
271
; This proc doesn't guarantee that after calling it and trying to use
-
 
272
; the port reported being free in calls to socket_open/socket_open_tcp it'll
-
 
273
; still be free or otherwise it'll still be used if reported being in use.
1213
;       edx = pointer to buffer
274
;
-
 
275
; @param BX is a port number
-
 
276
; @return 1 (port is free) or 0 (port is in use) in EAX
1214
;
277
;;
-
 
278
proc is_localport_unused stdcall
-
 
279
        movzx   ebx, bx
-
 
280
        mov     eax, [network_free_ports]
-
 
281
        bt      [eax], ebx
-
 
282
        setc    al
-
 
283
        movzx   eax, al
-
 
284
        ret
-
 
285
endp
-
 
286
 
-
 
287
;======================================
-
 
288
set_local_port:
-
 
289
;--------------------------------------
-
 
290
;? Set local port in socket structure.
1215
;  OUT: -1 on error
291
;--------------------------------------
-
 
292
;> eax -> struct SOCKET
-
 
293
;> bx = local port, or 0 if the kernel must select it itself
-
 
294
;--------------------------------------
-
 
295
;< CF set on error / cleared on success
-
 
296
;< [eax+SOCKET.LocalPort] filled on success
-
 
297
;======================================
-
 
298
; 0. Prepare: save registers, make eax point to ports table, expand port to ebx.
-
 
299
        push    eax ecx
-
 
300
        mov     eax, [network_free_ports]
1216
;-----------------------------------------------------------------
301
        movzx   ebx, bx
-
 
302
; 1. Test, whether the kernel should choose port itself. If no, proceed to 5.
-
 
303
        test    ebx, ebx
-
 
304
        jnz     .given
-
 
305
; 2. Yes, it should. Set ecx = limit of table, eax = start value
-
 
306
        lea     ecx, [eax+0x10000/8]
-
 
307
        add     eax, [network_free_hint]
-
 
308
; 3. First scan loop: from free hint to end of table.
-
 
309
.scan1:
-
 
310
; 3a. For each dword, find bit set to 1
-
 
311
        bsf     ebx, [eax]
-
 
312
        jz      .next1
-
 
313
; 3b. If such bit has been found, atomically test again and clear it.
-
 
314
        lock btr [eax], ebx
-
 
315
; 3c. If the bit was still set (usual case), we have found and reserved one port.
-
 
316
; Proceed to 6.
-
 
317
        jc      .found
-
 
318
; 3d. Otherwise, someone has reserved it between bsf and btr, so retry search.
-
 
319
        jmp     .scan1
-
 
320
.next1:
-
 
321
; 3e. All bits are cleared, so advance to next dword.
1217
align 4
322
        add     eax, 4
-
 
323
; 3f. Check limit and continue loop.
-
 
324
        cmp     eax, ecx
-
 
325
        jb      .scan1
-
 
326
; 4. Second scan loop: from port 1024 (start of non-system ports) to free hint.
-
 
327
        mov     eax, [network_free_ports]
-
 
328
        mov     ecx, eax
1218
SOCKET_debug:
329
        add     ecx, [network_free_hint]
-
 
330
        add     eax, 1024/8
-
 
331
; 4a. Test whether there is something to scan.
1219
 
332
        cmp     eax, ecx
-
 
333
        jae     .fail
-
 
334
; 4b. Enter the loop, the process is same as for 3.
-
 
335
.scan2:
-
 
336
        bsf     ebx, [eax]
1220
        DEBUGF  1,"SOCKET_debug\n"
337
        jz      .next2
-
 
338
        lock btr [eax], ebx
1221
 
339
        jc      .found
-
 
340
        jmp     .scan2
1222
        mov     edi, edx
341
.next2:
1223
 
342
        add     eax, 4
-
 
343
        cmp     eax, ecx
-
 
344
        jb      .scan2
-
 
345
; 4c. None found. Fail.
-
 
346
.fail:
-
 
347
        pop     ecx eax
-
 
348
        stc
1224
        test    ecx, ecx
Line 349... Line -...
349
        ret
-
 
350
; 5. No, the kernel should reserve selected port.
-
 
351
.given:
-
 
352
; 5a. Atomically test old value and clear bit.
-
 
353
        lock btr [eax], ebx
-
 
354
; 5b. If the bit was set, reservation is successful. Proceed to 8.
-
 
355
        jc      .set
-
 
356
; 5c. Otherwise, fail.
-
 
357
        jmp     .fail
-
 
358
.found:
-
 
359
; 6. We have found the bit set to 1, convert the position to port number.
-
 
Line -... Line 1225...
-
 
1225
        jz      .returnall
-
 
1226
 
-
 
1227
        call    SOCKET_num_to_ptr
-
 
1228
        jz      s_error
-
 
1229
 
-
 
1230
        mov     esi, eax
-
 
1231
        mov     ecx, SOCKETBUFFSIZE/4
-
 
1232
        rep     movsd
-
 
1233
 
-
 
1234
        mov     dword [esp+32], 0
-
 
1235
        ret
-
 
1236
 
-
 
1237
  .returnall:
-
 
1238
        mov     ebx, net_sockets
-
 
1239
  .next_socket:
360
        sub     eax, [network_free_ports]
1240
        mov     ebx, [ebx + SOCKET.NextPtr]
Line 361... Line 1241...
361
        lea     ebx, [ebx+eax*8]
1241
        test    ebx, ebx
Line 362... Line -...
362
; 7. Update free hint.
-
 
363
        add     eax, 4
-
 
364
        cmp     eax, 65536/8
-
 
365
        jb      @f
1242
        jz      .done
366
        mov     eax, 1024/8
1243
        mov     eax, [ebx + SOCKET.Number]
367
@@:
-
 
368
        mov     [network_free_hint], eax
-
 
Line 369... Line 1244...
369
.set:
1244
        stosd
-
 
1245
        jmp     .next_socket
-
 
1246
  .done:
370
; 8. Restore eax, set SOCKET.LocalPort and return.
1247
        xor     eax, eax
371
        pop     ecx eax
1248
        stosd
Line 372... Line 1249...
372
        xchg    bl, bh  ; Intel -> network byte order
1249
 
-
 
1250
        mov     dword [esp+32], 0
-
 
1251
        ret
373
        mov     [eax + SOCKET.LocalPort], bx
1252
 
Line 374... Line -...
374
        clc
-
 
375
        ret
-
 
376
 
1253
 
377
;; [53.0] Open DGRAM socket (connectionless, unreliable)
1254
;-----------------------------------------------------------------
378
;
-
 
Line -... Line 1255...
-
 
1255
;
-
 
1256
; SOCKET_find_port
-
 
1257
;
-
 
1258
; Fills in the local port number for TCP and UDP sockets
-
 
1259
; This procedure always works because the number of sockets is
-
 
1260
; limited to a smaller number then the number of possible ports
-
 
1261
;
-
 
1262
;  IN:  eax = socket pointer
-
 
1263
;  OUT: /
-
 
1264
;
-
 
1265
;-----------------------------------------------------------------
-
 
1266
align 4
-
 
1267
SOCKET_find_port:
-
 
1268
 
-
 
1269
        DEBUGF  2,"SOCKET_find_port\n"
-
 
1270
 
-
 
1271
        push    ebx esi ecx
-
 
1272
 
-
 
1273
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
-
 
1274
        je      .udp
-
 
1275
 
-
 
1276
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
-
 
1277
        je      .tcp
-
 
1278
 
-
 
1279
        pop     ecx esi ebx
-
 
1280
        ret
-
 
1281
 
-
 
1282
  .udp:
-
 
1283
        mov     bx, [last_UDP_port]
379
; @param BX is local port number
1284
        call    .findit
380
; @param CX is remote port number
1285
        mov     [last_UDP_port], bx
381
; @param EDX is remote IP address
1286
 
382
; @return socket number or -1 (error) in EAX
1287
        pop     ecx esi ebx
-
 
1288
        ret
383
;;
1289
 
384
proc socket_open stdcall
-
 
385
        call    net_socket_alloc
-
 
386
        or      eax, eax
1290
  .tcp:
-
 
1291
        mov     bx, [last_TCP_port]
387
        jz      .error
1292
        call    .findit
388
 
1293
        mov     [last_TCP_port], bx
Line 389... Line 1294...
389
        DEBUGF  1, "K : socket_open (0x%x)\n", eax
1294
 
390
 
-
 
Line 391... Line -...
391
        push    eax
-
 
392
 
1295
        pop     ecx esi ebx
393
        call    set_local_port
1296
        ret
394
        jc      .error.free
1297
 
Line 395... Line 1298...
395
        xchg    ch, cl
1298
 
396
        mov     [eax + SOCKET.RemotePort], cx
1299
  .restart:
397
        mov     ebx, [stack_ip]
1300
        mov     bx, MIN_EPHEMERAL_PORT_N
398
        mov     [eax + SOCKET.LocalIP], ebx
1301
  .findit:
399
        mov     [eax + SOCKET.RemoteIP], edx
-
 
400
 
-
 
-
 
1302
        cmp     bx, MAX_EPHEMERAL_PORT_N
401
        ;pop     eax      ; Get the socket number back, so we can return it
1303
        je      .restart
402
        stdcall net_socket_addr_to_num
1304
 
Line 403... Line 1305...
403
        ret
1305
        add     bh, 1
404
 
-
 
405
  .error.free:
-
 
406
        stdcall net_socket_free;, eax
1306
        adc     bl, 0
Line 407... Line 1307...
407
 
1307
 
408
  .error:
1308
        call    SOCKET_check_port
Line 409... Line -...
409
        DEBUGF  1, "K : socket_open (fail)\n"
-
 
410
        or      eax, -1
1309
        jz      .findit
411
        ret
-
 
412
endp
1310
        ret
Line -... Line 1311...
-
 
1311
 
-
 
1312
 
413
 
1313
 
-
 
1314
;-----------------------------------------------------------------
-
 
1315
;
Line 414... Line -...
414
;; [53.5] Open STREAM socket (connection-based, sequenced, reliable, two-way)
-
 
Line 415... Line -...
415
;
-
 
416
; @param BX is local port number
-
 
Line -... Line 1316...
-
 
1316
; SOCKET_check_port (to be used with AF_INET only!)
-
 
1317
;
-
 
1318
; Checks if a local port number is unused
-
 
1319
; If the proposed port number is unused, it is filled in in the socket structure
417
; @param CX is remote port number
1320
;
-
 
1321
;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
418
; @param EDX is remote IP address
1322
;        bx = proposed socket number (network byte order)
-
 
1323
;
419
; @param ESI is open mode (SOCKET_ACTIVE, SOCKET_PASSIVE)
1324
;  OUT:  ZF = set on error
420
; @return socket number or -1 (error) in EAX
1325
;
421
;;
1326
;-----------------------------------------------------------------
422
proc socket_open_tcp stdcall
1327
align 4
423
local sockAddr dd ?
1328
SOCKET_check_port:
-
 
1329
 
-
 
1330
        DEBUGF  2,"SOCKET_check_port: "
-
 
1331
 
424
 
1332
        mov     ecx, [eax + SOCKET.Protocol]
-
 
1333
        mov     edx, [eax + IP_SOCKET.LocalIP]
425
        cmp     esi, SOCKET_PASSIVE
1334
        mov     esi, net_sockets
Line 426... Line -...
426
        jne     .skip_port_check
-
 
427
 
-
 
428
        push    ebx
-
 
429
        mov     eax, ebx
-
 
430
        xchg    al, ah
-
 
431
        mov     ebx, net_sockets
1335
 
Line 432... Line 1336...
432
 
1336
  .next_socket:
433
  .next_socket:
1337
        mov     esi, [esi + SOCKET.NextPtr]
-
 
1338
        or      esi, esi
Line 434... Line 1339...
434
        mov     ebx, [ebx + SOCKET.NextPtr]
1339
        jz      .port_ok
435
        or      ebx, ebx
-
 
436
        jz      .last_socket
-
 
437
        cmp     [ebx + SOCKET.TCBState], TCB_LISTEN
-
 
438
        jne     .next_socket
-
 
Line 439... Line 1340...
439
        cmp     [ebx + SOCKET.LocalPort], ax
1340
 
-
 
1341
        cmp     [esi + SOCKET.Protocol], ecx
Line 440... Line 1342...
440
        jne     .next_socket
1342
        jne     .next_socket
441
 
1343
 
442
        xchg    al, ah
1344
        cmp     [esi + IP_SOCKET.LocalIP], edx
-
 
1345
        jne     .next_socket
Line 443... Line -...
443
        DEBUGF  1, "K : error: port %u is listened by 0x%x\n", ax, ebx
-
 
444
        pop     ebx
-
 
445
        jmp     .error
-
 
446
 
-
 
447
  .last_socket:
1346
 
448
        pop     ebx
-
 
Line 449... Line 1347...
449
 
1347
        cmp     [esi + UDP_SOCKET.LocalPort], bx
450
  .skip_port_check:
-
 
451
        call    net_socket_alloc
1348
        jne     .next_socket
452
        or      eax, eax
-
 
Line -... Line 1349...
-
 
1349
 
-
 
1350
        DEBUGF  2,"local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
453
        jz      .error
1351
        ret
-
 
1352
 
Line 454... Line -...
454
 
-
 
455
        DEBUGF  1, "K : socket_open_tcp (0x%x)\n", eax
1353
  .port_ok:
456
 
1354
        DEBUGF  2,"local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
Line 457... Line -...
457
        mov     [sockAddr], eax
-
 
458
 
-
 
459
        ; TODO - check this works!
-
 
460
        ;mov     [eax + SOCKET.wndsizeTimer], 0     ; Reset the window timer.
1355
        mov     [eax + UDP_SOCKET.LocalPort], bx
Line 461... Line -...
461
 
-
 
462
        call    set_local_port
-
 
Line -... Line 1356...
-
 
1356
        or      bx, bx                                  ; clear the zero-flag
-
 
1357
        ret
-
 
1358
 
-
 
1359
 
-
 
1360
 
-
 
1361
;-----------------------------------------------------------------
-
 
1362
;
-
 
1363
; SOCKET_input
-
 
1364
;
-
 
1365
; Updates a (stateless) socket with received data
-
 
1366
;
-
 
1367
; Note: the mutex should already be set !
-
 
1368
;
-
 
1369
;  IN:  eax = socket ptr
-
 
1370
;       ecx = data size
-
 
1371
;       esi = ptr to data
-
 
1372
;       [esp] = ptr to buf
-
 
1373
;       [esp + 4] = buf size
-
 
1374
;
463
        jc      .error.free
1375
;  OUT: /
-
 
1376
;
-
 
1377
;-----------------------------------------------------------------
-
 
1378
align 4
-
 
1379
SOCKET_input:
-
 
1380
 
-
 
1381
        DEBUGF  2,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
464
        xchg    ch, cl
1382
 
465
        mov     [eax + SOCKET.RemotePort], cx
1383
        mov     [esp+4], ecx
-
 
1384
        push    esi
-
 
1385
        mov     esi, esp
466
        mov     [eax + SOCKET.OrigRemotePort], cx
1386
 
467
        mov     ebx, [stack_ip]
-
 
Line 468... Line 1387...
468
        mov     [eax + SOCKET.LocalIP], ebx
1387
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
469
        mov     [eax + SOCKET.RemoteIP], edx
1388
 
470
        mov     [eax + SOCKET.OrigRemoteIP], edx
1389
        DEBUGF  1,"SOCKET_input: success\n"
-
 
1390
        add     esp, sizeof.socket_queue_entry
471
 
1391
 
472
        mov     ebx, TCB_LISTEN
1392
        pusha
473
        cmp     esi, SOCKET_PASSIVE
1393
        lea     ecx, [eax + SOCKET.mutex]
474
        je      @f
1394
        call    mutex_unlock
475
        mov     ebx, TCB_SYN_SENT
1395
        popa
-
 
1396
 
476
    @@:
1397
        jmp     SOCKET_notify
-
 
1398
 
-
 
1399
  .full:
-
 
1400
        DEBUGF  2,"SOCKET_input: socket %x is full!\n", eax
477
        mov     [eax + SOCKET.TCBState], ebx            ; Indicate the state of the TCB
1401
 
Line 478... Line 1402...
478
 
1402
        pusha
Line -... Line 1403...
-
 
1403
        lea     ecx, [eax + SOCKET.mutex]
-
 
1404
        call    mutex_unlock
-
 
1405
        popa
-
 
1406
 
-
 
1407
        call    kernel_free
-
 
1408
        add     esp, 8
-
 
1409
 
-
 
1410
        ret
-
 
1411
 
-
 
1412
 
-
 
1413
;--------------------------
479
        cmp     ebx, TCB_LISTEN
1414
;
-
 
1415
; eax = ptr to ring struct (just a buffer of the right size)
-
 
1416
;
-
 
1417
align 4
-
 
1418
SOCKET_ring_create:
-
 
1419
 
-
 
1420
        push    esi
-
 
1421
        mov     esi, eax
-
 
1422
 
-
 
1423
        push    edx
-
 
1424
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
-
 
1425
        pop     edx
-
 
1426
 
-
 
1427
        DEBUGF  1,"SOCKET_ring_created: %x\n", eax
-
 
1428
 
-
 
1429
        pusha
-
 
1430
        lea     ecx, [esi + RING_BUFFER.mutex]
-
 
1431
        call    mutex_init
-
 
1432
        popa
-
 
1433
 
-
 
1434
        mov     [esi + RING_BUFFER.start_ptr], eax
-
 
1435
        mov     [esi + RING_BUFFER.write_ptr], eax
-
 
1436
        mov     [esi + RING_BUFFER.read_ptr], eax
-
 
1437
        mov     [esi + RING_BUFFER.size], 0
-
 
1438
        add     eax, SOCKET_MAXDATA
-
 
1439
        mov     [esi + RING_BUFFER.end_ptr], eax
480
        je      .exit
1440
        mov     eax, esi
-
 
1441
        pop     esi
-
 
1442
 
-
 
1443
        ret
-
 
1444
 
-
 
1445
;-----------------------------------------------------------------
-
 
1446
;
-
 
1447
; SOCKET_ring_write
-
 
1448
;
-
 
1449
; Adds data to a stream socket, and updates write pointer and size
-
 
1450
;
-
 
1451
;  IN:  eax = ptr to ring struct
-
 
1452
;       ecx = data size
Line 481... Line -...
481
 
-
 
482
        ; Now, if we are in active mode, then we have to send a SYN to the specified remote port
-
 
483
        mov     eax, EMPTY_QUEUE
-
 
484
        call    dequeue
1453
;       esi = ptr to data
485
        cmp     ax, NO_BUFFER
-
 
Line -... Line 1454...
-
 
1454
;
-
 
1455
;  OUT: ecx = number of bytes stored
-
 
1456
;
-
 
1457
;-----------------------------------------------------------------
486
        je      .exit
1458
align 4
487
 
1459
SOCKET_ring_write:
-
 
1460
 
488
        push    eax
1461
        DEBUGF  1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
489
 
1462
 
490
        mov     bl, TH_SYN
1463
; lock mutex
491
        xor     ecx, ecx
1464
        pusha
-
 
1465
        lea     ecx, [eax + RING_BUFFER.mutex]
-
 
1466
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
-
 
1467
        popa
492
        stdcall build_tcp_packet, [sockAddr]
1468
 
493
 
1469
; calculate available size
-
 
1470
        mov     edi, SOCKET_MAXDATA
494
        mov     eax, NET1OUT_QUEUE
1471
        sub     edi, [eax + RING_BUFFER.size]                   ; available buffer size in edi
-
 
1472
        cmp     ecx, edi
-
 
1473
        jbe     .copy
Line 495... Line -...
495
        mov     edx, [stack_ip]
-
 
496
        mov     ecx, [sockAddr]
-
 
497
        cmp     edx, [ecx + SOCKET.RemoteIP]
1474
        mov     ecx, edi
-
 
1475
  .copy:
-
 
1476
        mov     edi, [eax + RING_BUFFER.write_ptr]
-
 
1477
        DEBUGF  2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
Line 498... Line 1478...
498
        jne     .not_local
1478
 
499
        mov     eax, IPIN_QUEUE
1479
; update write ptr
Line 500... Line -...
500
 
-
 
501
  .not_local:
-
 
502
        ; Send it.
-
 
503
        pop     ebx
1480
        push    edi
504
        call    queue
1481
        add     edi, ecx
505
 
-
 
506
        mov     esi, [sockAddr]
-
 
507
 
1482
        cmp     edi, [eax + RING_BUFFER.end_ptr]
Line 508... Line 1483...
508
        ; increment SND.NXT in socket
1483
        jb      @f
509
        add     esi, SOCKET.SND_NXT
1484
        sub     edi, SOCKET_MAXDATA                             ; WRAP
510
        call    inc_inet_esi
1485
  @@:
511
 
1486
        mov     [eax + RING_BUFFER.write_ptr], edi
512
  .exit:
-
 
Line -... Line 1487...
-
 
1487
        pop     edi
-
 
1488
 
-
 
1489
; update size
-
 
1490
        add     [eax + RING_BUFFER.size], ecx
-
 
1491
 
-
 
1492
; copy the data
-
 
1493
        push    ecx
-
 
1494
        shr     ecx, 1
-
 
1495
        jnc     .nb
-
 
1496
        movsb
-
 
1497
  .nb:
-
 
1498
        shr     ecx, 1
-
 
1499
        jnc     .nw
-
 
1500
        movsw
-
 
1501
  .nw:
-
 
1502
        test    ecx, ecx
-
 
1503
        jz      .nd
-
 
1504
        rep     movsd
-
 
1505
  .nd:
-
 
1506
        pop     ecx
-
 
1507
 
513
        ; Get the socket number back, so we can return it
1508
; unlock mutex
-
 
1509
        push    eax ecx
-
 
1510
        lea     ecx, [eax + RING_BUFFER.mutex]
-
 
1511
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
514
        stdcall net_socket_addr_to_num, [sockAddr]
1512
        pop     ecx eax
Line 515... Line 1513...
515
        ret
1513
 
516
 
1514
        ret
517
  .error.free:
1515
 
Line -... Line 1516...
-
 
1516
;-----------------------------------------------------------------
518
        stdcall net_socket_free, eax
1517
;
519
 
1518
; SOCKET_ring_read
Line 520... Line -...
520
  .error:
-
 
521
        DEBUGF  1, "K : socket_open_tcp (fail)\n"
-
 
522
        or      eax, -1
-
 
523
        ret
-
 
524
endp
-
 
525
 
-
 
526
;; [53.1] Close DGRAM socket
-
 
527
;
-
 
528
; @param EBX is socket number
-
 
529
; @return 0 (closed successfully) or -1 (error) in EAX
-
 
530
;;
-
 
531
proc socket_close stdcall
-
 
Line -... Line 1519...
-
 
1519
;
-
 
1520
;  IN:  eax = ring struct ptr
-
 
1521
;       ecx = bytes to read
-
 
1522
;       edx = offset
-
 
1523
;       edi = ptr to buffer start
-
 
1524
;
-
 
1525
;  OUT: eax = unchanged
532
        DEBUGF  1, "K : socket_close (0x%x)\n", ebx
1526
;       ecx = number of bytes read (0 on error)
-
 
1527
;       edx = destroyed
-
 
1528
;       esi = destroyed
-
 
1529
;       edi = ptr to buffer end
-
 
1530
;
-
 
1531
;-----------------------------------------------------------------
-
 
1532
align 4
Line 533... Line -...
533
        stdcall net_socket_num_to_addr, ebx
-
 
534
        or      eax, eax
-
 
535
        jz      .error
-
 
536
 
1533
SOCKET_ring_read:
Line 537... Line 1534...
537
        stdcall net_socket_free, eax
1534
 
538
 
-
 
539
        xor     eax, eax
-
 
540
        ret
-
 
541
 
-
 
542
  .error:
-
 
543
        DEBUGF  1, "K : socket_close (fail)\n"
1535
        DEBUGF  1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
544
        or      eax, -1
-
 
545
        ret
-
 
546
endp
-
 
547
 
-
 
548
;; [53.8] Close STREAM socket
-
 
549
; Closing TCP sockets takes time, so when you get successful return code
-
 
550
; from this function doesn't always mean that socket is actually closed.
1536
 
551
;
-
 
552
; @param EBX is socket number
1537
        pusha
553
; @return 0 (closed successfully) or -1 (error) in EAX
-
 
554
;;
-
 
555
proc socket_close_tcp stdcall
-
 
556
local sockAddr dd ?
-
 
557
 
-
 
558
        DEBUGF  1, "K : socket_close_tcp (0x%x)\n", ebx
-
 
559
        ; first, remove any resend entries
-
 
560
        pusha
-
 
561
 
-
 
562
        mov     esi, resendQ
-
 
563
        mov     ecx, 0
-
 
564
 
-
 
Line 565... Line -...
565
  .next_resendq:
-
 
566
        cmp     ecx, NUMRESENDENTRIES
-
 
567
        je      .last_resendq       ; None left
1538
        lea     ecx, [eax + RING_BUFFER.mutex]
568
        cmp     [esi + 4], ebx
1539
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
569
        je      @f                  ; found one
1540
        popa
Line -... Line 1541...
-
 
1541
 
-
 
1542
        mov     esi, [eax + RING_BUFFER.read_ptr]
-
 
1543
        add     esi, edx                                        ; esi = start_ptr + offset
-
 
1544
 
570
        inc     ecx
1545
        neg     edx
Line 571... Line 1546...
571
        add     esi, 8
1546
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
-
 
1547
        jle     .no_data_at_all
572
        jmp     .next_resendq
1548
 
-
 
1549
        pusha
Line 573... Line -...
573
 
-
 
574
    @@:
-
 
575
        mov     dword[esi + 4], 0
1550
        lea     ecx, [eax + RING_BUFFER.mutex]
Line -... Line 1551...
-
 
1551
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
-
 
1552
        popa
-
 
1553
 
-
 
1554
        cmp     ecx, edx
576
        inc     ecx
1555
        ja      .less_data
577
        add     esi, 8
1556
 
-
 
1557
  .copy:
-
 
1558
        DEBUGF  2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
-
 
1559
        push    ecx
578
        jmp     .next_resendq
1560
        shr     ecx, 1
579
 
1561
        jnc     .nb
580
  .last_resendq:
-
 
Line -... Line 1562...
-
 
1562
        movsb
581
        popa
1563
  .nb:
582
 
1564
        shr     ecx, 1
583
        stdcall net_socket_num_to_addr, ebx
1565
        jnc     .nw
-
 
1566
        movsw
584
        or      eax, eax
1567
  .nw:
585
        jz      .error
1568
        test    ecx, ecx
586
 
1569
        jz      .nd
587
        mov     ebx, eax
1570
        rep     movsd
-
 
1571
  .nd:
588
        mov     [sockAddr], eax
1572
        pop     ecx
589
 
1573
        ret
590
        cmp     [ebx + SOCKET.TCBState], TCB_LISTEN
1574
 
Line -... Line 1575...
-
 
1575
  .no_data_at_all:
-
 
1576
        pusha
-
 
1577
        lea     ecx, [eax + RING_BUFFER.mutex]
-
 
1578
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
-
 
1579
        popa
-
 
1580
 
-
 
1581
        DEBUGF  1,"SOCKET_ring_read: no data at all!\n"
-
 
1582
        xor     ecx, ecx
-
 
1583
        ret
-
 
1584
 
-
 
1585
  .less_data:
-
 
1586
        mov     ecx, edx
-
 
1587
        jmp     .copy
-
 
1588
 
-
 
1589
 
-
 
1590
;-----------------------------------------------------------------
591
        je      .destroy_tcb
1591
;
-
 
1592
; SOCKET_ring_free
-
 
1593
;
-
 
1594
; Free's some bytes from the ringbuffer
592
        cmp     [ebx + SOCKET.TCBState], TCB_SYN_SENT
1595
;
-
 
1596
;  IN:  eax = ptr to ring struct
-
 
1597
;       ecx = data size
Line 593... Line -...
593
        je      .destroy_tcb
-
 
594
        cmp     [ebx + SOCKET.TCBState], TCB_CLOSED
-
 
595
        je      .destroy_tcb
1598
;
596
 
-
 
Line -... Line 1599...
-
 
1599
;  OUT: ecx = number of bytes free-ed
597
        ; Now construct the response, and queue for sending by IP
1600
;
598
        mov     eax, EMPTY_QUEUE
1601
;-----------------------------------------------------------------
599
        call    dequeue
1602
align 4
-
 
1603
SOCKET_ring_free:
600
        cmp     ax, NO_BUFFER
1604
 
601
        je      .error
1605
        DEBUGF  1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
602
 
1606
 
603
        push    eax
1607
        push    eax ecx
-
 
1608
        lea     ecx, [eax + RING_BUFFER.mutex]
604
 
1609
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
605
        mov     bl, TH_FIN+TH_ACK
1610
        pop     ecx eax
606
        xor     ecx, ecx
1611
 
Line 607... Line 1612...
607
        xor     esi, esi
1612
        sub     [eax + RING_BUFFER.size], ecx
608
        stdcall build_tcp_packet, [sockAddr]
-
 
Line 609... Line -...
609
 
-
 
610
        mov     ebx, [sockAddr]
1613
        jb      .error
611
        ; increament SND.NXT in socket
1614
        add     [eax + RING_BUFFER.read_ptr], ecx
612
        lea     esi, [ebx + SOCKET.SND_NXT]
-
 
Line 613... Line -...
613
        call    inc_inet_esi
-
 
614
 
-
 
615
        ; Get the socket state
-
 
616
        mov     eax, [ebx + SOCKET.TCBState]
1615
 
617
        cmp     eax, TCB_SYN_RECEIVED
-
 
618
        je      .fin_wait_1
1616
        mov     edx, [eax + RING_BUFFER.end_ptr]
619
        cmp     eax, TCB_ESTABLISHED
-
 
620
        je      .fin_wait_1
-
 
621
 
1617
        cmp     [eax + RING_BUFFER.read_ptr], edx
622
        ; assume CLOSE WAIT
-
 
623
        ; Send a fin, then enter last-ack state
-
 
624
        mov     [ebx + SOCKET.TCBState], TCB_LAST_ACK
1618
        jb      @f
625
        jmp     .send
-
 
626
 
1619
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
Line 627... Line 1620...
627
  .fin_wait_1:
1620
       @@:
-
 
1621
 
628
        ; Send a fin, then enter finwait2 state
1622
        push    eax ecx
629
        mov     [ebx + SOCKET.TCBState], TCB_FIN_WAIT_1
1623
        lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
Line 630... Line 1624...
630
 
1624
        call    mutex_unlock
631
  .send:
1625
        pop     ecx eax
632
        mov     eax, NET1OUT_QUEUE
1626
 
-
 
1627
        ret
-
 
1628
 
-
 
1629
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
-
 
1630
        DEBUGF  1,"SOCKET_ring_free: buffer=%x error!\n", eax
-
 
1631
        add     [eax + RING_BUFFER.size], ecx
-
 
1632
 
-
 
1633
        push    eax
-
 
1634
        lea     ecx, [eax + RING_BUFFER.mutex]
-
 
1635
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
-
 
1636
        pop     eax
-
 
1637
 
-
 
1638
        xor     ecx, ecx
-
 
1639
        ret
-
 
1640
 
-
 
1641
 
-
 
1642
;-----------------------------------------------------------------
-
 
1643
;
-
 
1644
; SOCKET_block
-
 
1645
;
-
 
1646
; Suspends the thread attached to a socket
-
 
1647
;
-
 
1648
;  IN:  eax = socket ptr
-
 
1649
;  OUT: /
-
 
1650
;
-
 
1651
;-----------------------------------------------------------------
Line 633... Line 1652...
633
        mov     edx, [stack_ip]
1652
align 4
634
        mov     ecx, [sockAddr]
1653
SOCKET_block:
635
        cmp     edx, [ecx + SOCKET.RemoteIP]
1654
 
636
        jne     .not_local
1655
        DEBUGF  1,"SOCKET_block: %x\n", eax
637
        mov     eax, IPIN_QUEUE
-
 
638
 
1656
 
639
  .not_local:
1657
        pushf
640
        ; Send it.
1658
        cli
641
        pop     ebx
1659
 
-
 
1660
        ; Set the 'socket is blocked' flag
642
        call    queue
1661
        or      [eax + SOCKET.state], SS_BLOCKED
643
        jmp     .exit
1662
 
644
 
1663
        ; Suspend the thread
645
  .destroy_tcb:
1664
        push    edx
646
 
1665
        mov     edx, [TASK_BASE]
647
        ; Clear the socket variables
1666
        mov     [edx + TASKDATA.state], 1               ; Suspended
-
 
1667
 
Line 648... Line 1668...
648
        stdcall net_socket_free, ebx
1668
        ; Remember the thread ID so we can wake it up again
649
 
1669
        mov     edx, [edx + TASKDATA.pid]
650
  .exit:
1670
        DEBUGF  1,"SOCKET_block: suspending thread: %u\n", edx
-
 
1671
        mov     [eax + SOCKET.TID], edx
-
 
1672
        pop     edx
651
        xor     eax, eax
1673
 
652
        ret
-
 
Line 653... Line -...
653
 
-
 
654
  .error:
-
 
655
        DEBUGF  1, "K : socket_close_tcp (fail)\n"
-
 
656
        or      eax, -1
1674
        call    change_task
657
        ret
-
 
658
endp
-
 
659
 
1675
        popf
660
;; [53.2] Poll socket
-
 
Line -... Line 1676...
-
 
1676
 
661
;
1677
        DEBUGF  1,"SOCKET_block: continueing\n"
-
 
1678
 
-
 
1679
        ret
-
 
1680
 
662
; @param EBX is socket number
1681
 
663
; @return count or bytes in rx buffer or 0 (error) in EAX
-
 
664
;;
1682
;-----------------------------------------------------------------
665
proc socket_poll stdcall
1683
;
666
;        DEBUGF  1, "socket_poll(0x%x)\n", ebx
1684
; SOCKET_notify
-
 
1685
;
-
 
1686
; notify's the owner of a socket that something happened
667
        stdcall net_socket_num_to_addr, ebx
1687
;
668
        or      eax, eax
1688
;  IN:  eax = socket ptr
-
 
1689
;  OUT: /
669
        jz      .error
1690
;
-
 
1691
;-----------------------------------------------------------------
-
 
1692
align 4
-
 
1693
SOCKET_notify:
670
 
1694
 
671
        mov     eax, [eax + SOCKET.rxDataCount]
1695
        DEBUGF  1,"SOCKET_notify: %x\n", eax
672
        ret
1696
 
673
 
1697
        call    SOCKET_check
674
  .error:
-
 
675
        xor     eax, eax
1698
        jz      .error
676
        ret
1699
 
Line -... Line 1700...
-
 
1700
        test    [eax + SOCKET.state], SS_BLOCKED
-
 
1701
        jnz     .unblock
677
endp
1702
 
-
 
1703
        test    [eax + SOCKET.options], SO_NONBLOCK
-
 
1704
        jz      .error
-
 
1705
 
-
 
1706
        push    eax ecx esi
-
 
1707
 
-
 
1708
; socket exists and is of non blocking type.
-
 
1709
; We'll try to flag an event to the thread
-
 
1710
 
-
 
1711
        mov     eax, [eax + SOCKET.TID]
-
 
1712
        test    eax, eax
-
 
1713
        jz      .done
-
 
1714
        mov     ecx, 1
-
 
1715
        mov     esi, TASK_DATA + TASKDATA.pid
-
 
1716
 
-
 
1717
  .next_pid:
-
 
1718
        cmp     [esi], eax
-
 
1719
        je      .found_pid
-
 
1720
        inc     ecx
-
 
1721
        add     esi, 0x20
-
 
1722
        cmp     ecx, [TASK_COUNT]
-
 
1723
        jbe     .next_pid
Line -... Line 1724...
-
 
1724
; PID not found, TODO: close socket!
678
 
1725
        jmp     .done
-
 
1726
 
-
 
1727
  .found_pid:
-
 
1728
        shl     ecx, 8
-
 
1729
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
-
 
1730
 
-
 
1731
        DEBUGF  1,"SOCKET_notify: Raised a network event!\n"
-
 
1732
 
-
 
1733
        jmp     .done
-
 
1734
 
-
 
1735
  .unblock:
-
 
1736
        push    eax ecx esi
-
 
1737
        ; Clear the 'socket is blocked' flag
-
 
1738
        and     [eax + SOCKET.state], not SS_BLOCKED
-
 
1739
 
-
 
1740
        ; Find the thread's TASK_DATA
679
;; [53.6] Get socket TCB state
1741
        mov     eax, [eax + SOCKET.TID]
680
;
1742
        test    eax, eax
681
; @param EBX is socket number
1743
        jz      .error
Line 682... Line 1744...
682
; @return socket TCB state or 0 (error) in EAX
1744
        xor     ecx, ecx
683
;;
-
 
684
proc socket_status stdcall
-
 
685
;;       DEBUGF  1, "socket_status(0x%x)\n", ebx
-
 
686
        stdcall net_socket_num_to_addr, ebx
-
 
687
        or      eax, eax
-
 
688
        jz      .error
-
 
689
 
1745
        inc     ecx
Line 690... Line -...
690
        mov     eax, [eax + SOCKET.TCBState]
-
 
691
        ret
1746
        mov     esi, TASK_DATA
692
 
1747
  .next:
693
  .error:
-
 
694
        xor     eax, eax
-
 
Line 695... Line -...
695
        ret
-
 
696
endp
-
 
697
 
-
 
698
;; [53.3] Get one byte from rx buffer
-
 
699
; This function can return 0 in two cases: if there's one byte read and
-
 
700
; non left, and if an error occured. Behavior should be changed and function
-
 
701
; shouldn't be used for now. Consider using [53.11] instead.
-
 
702
;
-
 
703
; @param EBX is socket number
-
 
704
; @return number of bytes left in rx buffer or 0 (error) in EAX
1748
        cmp     [esi + TASKDATA.pid], eax
705
; @return byte read in BL
1749
        je      .found
706
;;
-
 
Line 707... Line 1750...
707
proc socket_read stdcall
1750
        inc     ecx
708
;        DEBUGF  1, "socket_read(0x%x)\n", ebx
1751
        add     esi, 0x20
709
        stdcall net_socket_num_to_addr, ebx
-
 
710
        or      eax, eax
1752
        cmp     ecx, [TASK_COUNT]
711
        jz      .error
1753
        jbe     .next
712
 
-
 
Line 713... Line -...
713
        mov     ebx, eax
-
 
714
        lea     ecx, [eax + SOCKET.mutex]
1754
        jmp     .error
715
        call    mutex_lock
-
 
Line 716... Line -...
716
 
-
 
717
        mov     eax, [ebx + SOCKET.rxDataCount]         ; get count of bytes
1755
  .found:
718
        test    eax, eax
-
 
719
        jz      .error_release
-
 
720
 
1756
 
721
        dec     eax
-
 
722
        mov     esi, ebx                                ; esi is address of socket
1757
        ; Run the thread
-
 
1758
        mov     [esi + TASKDATA.state], 0       ; Running
-
 
1759
        DEBUGF  1,"SOCKET_notify: Unblocked socket!\n"
-
 
1760
 
-
 
1761
  .done:
-
 
1762
        pop     esi ecx eax
-
 
1763
 
723
        mov     [ebx + SOCKET.rxDataCount], eax         ; store new count
1764
  .error:
-
 
1765
        ret
724
        movzx   eax, byte[ebx + SOCKET.rxData]          ; get the byte
1766
 
Line 725... Line 1767...
725
 
1767
 
726
        mov     ecx, SOCKETBUFFSIZE - SOCKET.rxData - 1
-
 
727
        lea     edi, [esi + SOCKET.rxData]
-
 
728
        lea     esi, [edi + 1]
-
 
729
        cld
-
 
730
        push    ecx
-
 
731
        shr     ecx, 2
1768
;--------------------------------------------------------------------
732
        rep movsd
-
 
733
        pop     ecx
-
 
734
        and     ecx, 3
-
 
735
        rep movsb
-
 
736
 
-
 
737
        lea     ecx, [ebx + SOCKET.mutex]
-
 
738
        mov     ebx, eax
1769
;
-
 
1770
; SOCKET_alloc
739
        call    mutex_unlock
1771
;
740
        mov     eax, ebx
1772
; Allocate memory for socket data and put new socket into the list
741
        ret
1773
; Newly created socket is initialized with calling PID and number and
742
 
1774
; put into beginning of list (which is a fastest way).
743
  .error_release:
-
 
744
        lea     ecx, [ebx + SOCKET.mutex]
1775
;
745
        call    mutex_unlock
-
 
746
  .error:
1776
; IN:  /
-
 
1777
; OUT: eax = 0 on error, socket ptr otherwise
-
 
1778
;      edi = socket number
747
        xor     ebx, ebx
1779
;       ZF = cleared on error
-
 
1780
;
748
        xor     eax, eax
1781
;--------------------------------------------------------------------
749
        ret
-
 
-
 
1782
align 4
750
endp
1783
SOCKET_alloc:
751
 
1784
 
Line -... Line 1785...
-
 
1785
        push    ebx
-
 
1786
 
-
 
1787
        stdcall kernel_alloc, SOCKETBUFFSIZE
-
 
1788
        DEBUGF  1, "SOCKET_alloc: ptr=%x\n", eax
-
 
1789
        or      eax, eax
-
 
1790
        jz      .exit
-
 
1791
 
-
 
1792
; zero-initialize allocated memory
-
 
1793
        push    eax
-
 
1794
        mov     edi, eax
-
 
1795
        mov     ecx, SOCKETBUFFSIZE / 4
-
 
1796
        xor     eax, eax
-
 
1797
        rep     stosd
752
;; [53.11] Get specified number of bytes from rx buffer
1798
        pop     eax
-
 
1799
 
-
 
1800
; set send-and receive procedures to return -1
-
 
1801
        mov     [eax + SOCKET.snd_proc], s_error
-
 
1802
        mov     [eax + SOCKET.rcv_proc], s_error
Line 753... Line 1803...
753
; Number of bytes in rx buffer can be less than requested size. In this case,
1803
 
754
; only available number of bytes is read.
-
 
755
; This function can return 0 in two cases: if there's no data to read, and if
1804
; find first free socket number and use it
756
; an error occured. Behavior should be changed.
1805
        mov     edi, [last_socket_num]
Line 757... Line 1806...
757
;
1806
  .next_socket_number:
758
; @param EBX is socket number
-
 
Line 759... Line 1807...
759
; @param ECX is pointer to application buffer
1807
        inc     edi
760
; @param EDX is application buffer size (number of bytes to read)
1808
        jz      .next_socket_number     ; avoid socket nr 0
-
 
1809
        cmp     edi, -1
761
; @return number of bytes read or 0 (error) in EAX
1810
        je      .next_socket_number     ; avoid socket nr -1
Line 762... Line -...
762
;;
-
 
763
proc socket_read_packet stdcall
1811
        mov     ebx, net_sockets
764
;        DEBUGF  1, "socket_read_packet(0x%x)\n", ebx
1812
  .next_socket:
765
        stdcall net_socket_num_to_addr, ebx                ; get real socket address
1813
        mov     ebx, [ebx + SOCKET.NextPtr]
-
 
1814
        test    ebx, ebx
Line -... Line 1815...
-
 
1815
        jz      .last_socket
766
        or      eax, eax
1816
 
Line 767... Line 1817...
767
        jz      .error
1817
        cmp     [ebx + SOCKET.Number], edi
Line 768... Line -...
768
 
-
 
769
        mov     ebx, eax
1818
        jne     .next_socket
770
 
-
 
771
        push    ecx edx
1819
        jmp     .next_socket_number
772
        lea     ecx, [eax + SOCKET.mutex]
-
 
Line -... Line 1820...
-
 
1820
 
-
 
1821
  .last_socket:
-
 
1822
        mov     [last_socket_num], edi
-
 
1823
        mov     [eax + SOCKET.Number], edi
-
 
1824
        DEBUGF  1, "SOCKET_alloc: number=%u\n", edi
-
 
1825
 
773
        call    mutex_lock
1826
; Fill in PID
774
        pop     edx ecx
1827
        mov     ebx, [TASK_BASE]
-
 
1828
        mov     ebx, [ebx + TASKDATA.pid]
-
 
1829
        mov     [eax + SOCKET.PID], ebx
-
 
1830
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
-
 
1831
 
Line 775... Line -...
775
 
-
 
776
        mov     eax, [ebx + SOCKET.rxDataCount]            ; get count of bytes
1832
; init mutex
Line 777... Line -...
777
        test    eax, eax                                   ; if count of bytes is zero..
-
 
778
        jz      .exit                                      ; exit function (eax will be zero)
-
 
779
 
-
 
780
        test    edx, edx                                   ; if buffer size is zero, copy all data
-
 
781
        jz      .copy_all_bytes
-
 
782
        cmp     edx, eax                                   ; if buffer size is larger then the bytes of data, copy all data
-
 
783
        jge     .copy_all_bytes
-
 
784
 
-
 
785
        sub     eax, edx                                   ; store new count (data bytes in buffer - bytes we're about to copy)
-
 
786
        mov     [ebx + SOCKET.rxDataCount], eax            ;
1833
        pusha
787
        push    eax
1834
        lea     ecx, [eax + SOCKET.mutex]
788
        mov     eax, edx                                   ; number of bytes we want to copy must be in eax
-
 
789
        call    .start_copy                                ; copy to the application
-
 
790
 
1835
        call    mutex_init
791
        mov     esi, ebx                                   ; now we're going to copy the remaining bytes to the beginning
1836
        popa
Line -... Line 1837...
-
 
1837
 
-
 
1838
; add socket to the list by re-arranging some pointers
792
        add     esi, SOCKET.rxData                         ; we dont need to copy the header
1839
        mov     ebx, [net_sockets + SOCKET.NextPtr]
-
 
1840
 
793
        mov     edi, esi                                   ; edi is where we're going to copy to
1841
        mov     [eax + SOCKET.PrevPtr], net_sockets
Line 794... Line -...
794
        add     esi, edx                                   ; esi is from where we copy
-
 
795
        pop     ecx                                        ; count of bytes we have left
1842
        mov     [eax + SOCKET.NextPtr], ebx
-
 
1843
 
-
 
1844
        test    ebx, ebx
-
 
1845
        jz      @f
Line -... Line 1846...
-
 
1846
 
-
 
1847
        pusha
-
 
1848
        lea     ecx, [ebx + SOCKET.mutex]
796
        push    ecx                                        ; push it again so we can re-use it later
1849
        call    mutex_lock
-
 
1850
        popa
797
        shr     ecx, 2                                     ; divide eax by 4
1851
 
-
 
1852
        mov     [ebx + SOCKET.PrevPtr], eax
798
        cld
1853
 
-
 
1854
        pusha
-
 
1855
        lea     ecx, [ebx + SOCKET.mutex]
Line -... Line 1856...
-
 
1856
        call    mutex_unlock
-
 
1857
        popa
-
 
1858
       @@:
799
        rep movsd                                          ; copy all full dwords
1859
 
800
        pop     ecx
1860
        mov     [net_sockets + SOCKET.NextPtr], eax
801
        and     ecx, 3
1861
        or      eax, eax                ; used to clear zero flag
Line 802... Line -...
802
        rep movsb                                          ; copy remaining bytes
-
 
803
 
-
 
804
  .exit:
-
 
805
        lea     ecx, [ebx + SOCKET.mutex]
-
 
806
        mov     ebx, eax
-
 
807
        call    mutex_unlock
-
 
808
        mov     eax, ebx
-
 
809
        ret                    ; at last, exit
-
 
810
 
-
 
Line 811... Line 1862...
811
  .error:
1862
  .exit:
-
 
1863
        pop     ebx
812
        xor     eax, eax
1864
 
813
        ret
1865
        ret
814
 
1866
 
815
  .copy_all_bytes:
1867
 
816
        xor     esi, esi
1868
;----------------------------------------------------
817
        mov     [ebx + SOCKET.rxDataCount], esi            ; store new count (zero)
-
 
818
        call    .start_copy
1869
;
819
        lea     ecx, [ebx + SOCKET.mutex]
-
 
820
        mov     ebx, eax
1870
; SOCKET_free
-
 
1871
;
821
        call    mutex_unlock
1872
; Free socket data memory and remove socket from the list
822
        mov     eax, ebx
-
 
823
        ret
-
 
824
 
1873
;
825
  .start_copy:
-
 
826
        mov     edi, ecx
1874
; IN:  eax = socket ptr
827
        mov     esi, ebx
-
 
Line 828... Line -...
828
        add     esi, SOCKET.rxData                         ; we dont need to copy the header
-
 
829
        mov     ecx, eax                                   ; eax is count of bytes
-
 
830
        push    ecx
-
 
831
        shr     ecx, 2                                     ; divide eax by 4
-
 
832
        cld                                                ; copy all full dwords
-
 
833
        rep movsd
-
 
834
        pop     ecx
-
 
835
        and     ecx, 3
1875
; OUT: /
Line 836... Line 1876...
836
        rep movsb                                          ; copy the rest bytes
1876
;
Line -... Line 1877...
-
 
1877
;----------------------------------------------------
837
        retn                                               ; exit, or go back to shift remaining bytes if any
1878
align 4
-
 
1879
SOCKET_free:
-
 
1880
 
-
 
1881
        DEBUGF  1, "SOCKET_free: %x\n", eax
838
endp
1882
 
Line 839... Line -...
839
 
-
 
840
;; [53.4] Send data through DGRAM socket
-
 
841
;
1883
        call    SOCKET_check
842
; @param EBX is socket number
-
 
843
; @param ECX is application data size (number of bytes to send)
-
 
Line 844... Line -...
844
; @param EDX is pointer to application data buffer
-
 
845
; @return 0 (sent successfully) or -1 (error) in EAX
1884
        jz      .error
846
;;
1885
 
Line 847... Line 1886...
847
proc socket_write stdcall
1886
        push    ebx
848
;        DEBUGF  1, "socket_write(0x%x)\n", ebx
-
 
849
        stdcall net_socket_num_to_addr, ebx                ; get real socket address
1887
 
850
        or      eax, eax
1888
        pusha
851
        jz      .error
-
 
Line 852... Line -...
852
 
-
 
853
        mov     ebx, eax
-
 
Line -... Line 1889...
-
 
1889
        lea     ecx, [eax + SOCKET.mutex]
-
 
1890
        call    mutex_lock
-
 
1891
        popa
-
 
1892
 
-
 
1893
        cmp     [eax + SOCKET.Domain], AF_INET4
-
 
1894
        jnz     .no_tcp
-
 
1895
 
-
 
1896
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
854
 
1897
        jnz     .no_tcp
-
 
1898
 
-
 
1899
        mov     ebx, eax
-
 
1900
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
-
 
1901
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
Line 855... Line -...
855
        mov     eax, EMPTY_QUEUE
-
 
856
        call    dequeue
1902
        mov     eax, ebx
857
        cmp     ax, NO_BUFFER
-
 
858
        je      .error
-
 
859
 
-
 
860
        ; Save the queue entry number
-
 
861
        push    eax
-
 
862
 
-
 
863
        ; save the pointers to the data buffer & size
-
 
864
        push    edx
-
 
Line -... Line 1903...
-
 
1903
  .no_tcp:
865
        push    ecx
1904
 
-
 
1905
        push    eax                             ; this will be passed to kernel_free
-
 
1906
        mov     ebx, [eax + SOCKET.NextPtr]
-
 
1907
        mov     eax, [eax + SOCKET.PrevPtr]
-
 
1908
 
866
 
1909
        DEBUGF  1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
Line 867... Line 1910...
867
        ; convert buffer pointer eax to the absolute address
1910
 
868
        mov     ecx, IPBUFFSIZE
1911
        test    eax, eax
869
        mul     ecx
1912
        jz      @f
870
        add     eax, IPbuffs
-
 
Line -... Line 1913...
-
 
1913
        mov     [eax + SOCKET.NextPtr], ebx
871
 
1914
       @@:
872
        mov     edx, eax
1915
 
873
 
1916
        test    ebx, ebx
-
 
1917
        jz      @f
874
        ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
1918
        mov     [ebx + SOCKET.PrevPtr], eax
-
 
1919
       @@:
-
 
1920
 
875
 
1921
        call    kernel_free
876
        ; Fill in the IP header (some data is in the socket descriptor)
1922
        pop     ebx
877
        mov     eax, [ebx + SOCKET.LocalIP]
1923
 
878
        mov     [edx + IP_PACKET.SourceAddress], eax
1924
        DEBUGF  1, "SOCKET_free: success!\n"
-
 
1925
 
879
        mov     eax, [ebx + SOCKET.RemoteIP]
1926
  .error:
Line 880... Line 1927...
880
        mov     [edx + IP_PACKET.DestinationAddress], eax
1927
        ret
881
 
-
 
882
        mov     [edx + IP_PACKET.VersionAndIHL], 0x45
-
 
883
        mov     [edx + IP_PACKET.TypeOfService], 0
-
 
Line 884... Line 1928...
884
 
1928
 
885
        pop     eax                   ; Get the UDP data length
1929
;------------------------------------
Line 886... Line 1930...
886
        push    eax
1930
;
887
 
1931
; SOCKET_fork
888
        add     eax, 20 + 8           ; add IP header and UDP header lengths
1932
;
889
        xchg    al, ah
-
 
890
        mov     [edx + IP_PACKET.TotalLength], ax
-
 
891
        xor     eax, eax
1933
; Create a child socket
892
        mov     [edx + IP_PACKET.Identification], ax
1934
;
893
        mov     [edx + IP_PACKET.FlagsAndFragmentOffset], 0x0040
1935
; IN:  socket nr in ebx
Line -... Line 1936...
-
 
1936
; OUT: child socket nr in eax
-
 
1937
;
-
 
1938
;-----------------------------------
894
        mov     [edx + IP_PACKET.TimeToLive], 0x20
1939
align 4
Line 895... Line -...
895
        mov     [edx + IP_PACKET.Protocol], PROTOCOL_UDP
-
 
896
 
-
 
897
        ; Checksum left unfilled
-
 
898
        mov     [edx + IP_PACKET.HeaderChecksum], ax
-
 
899
 
1940
SOCKET_fork:
Line 900... Line -...
900
        ; Fill in the UDP header (some data is in the socket descriptor)
-
 
901
        mov     ax, [ebx + SOCKET.LocalPort]
-
 
Line 902... Line -...
902
        mov     [edx + 20 + UDP_PACKET.SourcePort], ax
-
 
903
 
-
 
904
        mov     ax, [ebx + SOCKET.RemotePort]
-
 
905
        mov     [edx + 20 + UDP_PACKET.DestinationPort], ax
-
 
Line -... Line 1941...
-
 
1941
 
-
 
1942
        DEBUGF  1,"SOCKET_fork: %x\n", ebx
-
 
1943
 
-
 
1944
; Exit if backlog queue is full
906
 
1945
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
-
 
1946
        cmp     ax, [ebx + SOCKET.backlog]
-
 
1947
        jae     .fail
-
 
1948
 
-
 
1949
; Allocate new socket
-
 
1950
        push    ebx
-
 
1951
        call    SOCKET_alloc
-
 
1952
        pop     ebx
-
 
1953
        jz      .fail
907
        pop     eax
1954
 
Line -... Line 1955...
-
 
1955
        push    eax
-
 
1956
        mov     esi, esp
-
 
1957
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
-
 
1958
        pop     eax
908
        push    eax
1959
 
909
 
-
 
Line 910... Line -...
910
        add     eax, 8
-
 
911
        xchg    al, ah
-
 
912
        mov     [edx + 20 + UDP_PACKET.Length], ax
-
 
913
 
-
 
914
        ; Checksum left unfilled
1960
; Copy structure from current socket to new
915
        xor     eax, eax
-
 
Line 916... Line -...
916
        mov     [edx + 20 + UDP_PACKET.Checksum], ax
-
 
917
 
-
 
918
        pop     ecx                  ; count of bytes to send
-
 
Line 919... Line -...
919
        mov     ebx, ecx             ; need the length later
-
 
Line 920... Line -...
920
        pop     eax                  ; get callers ptr to data to send
-
 
Line -... Line 1961...
-
 
1961
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
-
 
1962
        lea     esi, [ebx + SOCKET.PID]
-
 
1963
        lea     edi, [eax + SOCKET.PID]
-
 
1964
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
-
 
1965
        rep     movsd
-
 
1966
 
-
 
1967
        and     [eax + SOCKET.options], not SO_ACCEPTCON
-
 
1968
 
-
 
1969
        ret
-
 
1970
 
-
 
1971
  .fail2:
-
 
1972
        add     esp, 4+4+4
-
 
1973
  .fail:
-
 
1974
        DEBUGF  1,"SOCKET_fork: failed\n"
-
 
1975
        xor     eax, eax
-
 
1976
        ret
-
 
1977
 
-
 
1978
 
921
 
1979
;---------------------------------------------------
-
 
1980
;
-
 
1981
; SOCKET_num_to_ptr
-
 
1982
;
-
 
1983
; Get socket structure address by its number
-
 
1984
;
-
 
1985
; IN:  ecx = socket number
-
 
1986
; OUT: eax = 0 on error, socket ptr otherwise
922
        ; Get the address of the callers data
1987
;       ZF = set on error
-
 
1988
;
-
 
1989
;---------------------------------------------------
-
 
1990
align 4
-
 
1991
SOCKET_num_to_ptr:
923
        mov     edi, [TASK_BASE]
1992
 
-
 
1993
        DEBUGF  1,"SOCKET_num_to_ptr: num=%u ", ecx
-
 
1994
 
-
 
1995
        mov     eax, net_sockets
-
 
1996
 
-
 
1997
  .next_socket:
924
        add     edi, TASKDATA.mem_start
1998
        mov     eax, [eax + SOCKET.NextPtr]
Line -... Line 1999...
-
 
1999
        or      eax, eax
925
        add     eax, [edi]
2000
        jz      .error
Line 926... Line -...
926
        mov     esi, eax
-
 
927
 
-
 
928
        mov     edi, edx
-
 
929
        add     edi, 28
-
 
930
        cld
-
 
931
        rep movsb                   ; copy the data across
-
 
932
 
-
 
933
        ; we have edx as IPbuffer ptr.
-
 
934
        ; Fill in the UDP checksum
-
 
935
        ; First, fill in pseudoheader
-
 
936
        mov     eax, [edx + IP_PACKET.SourceAddress]
2001
        cmp     [eax + SOCKET.Number], ecx
937
        mov     [pseudoHeader], eax
-
 
938
        mov     eax, [edx + IP_PACKET.DestinationAddress]
-
 
Line 939... Line -...
939
        mov     [pseudoHeader + 4], eax
-
 
940
        mov     word[pseudoHeader + 8], PROTOCOL_UDP shl 8 + 0      ; 0 + protocol
-
 
Line 941... Line -...
941
        add     ebx, 8
-
 
942
        mov     eax, ebx
-
 
943
        xchg    al, ah
-
 
944
        mov     [pseudoHeader + 10], ax
-
 
945
 
-
 
946
        mov     eax, pseudoHeader
-
 
947
        mov     [checkAdd1], eax
-
 
948
        mov     [checkSize1], word 12
-
 
949
        mov     eax, edx
-
 
950
        add     eax, 20
-
 
951
        mov     [checkAdd2], eax
-
 
952
        mov     eax, ebx
-
 
Line 953... Line -...
953
        mov     [checkSize2], ax      ; was eax!! mjh 8/7/02
-
 
954
 
-
 
955
        call    checksum
-
 
Line -... Line 2002...
-
 
2002
        jne     .next_socket
956
 
2003
 
957
        ; store it in the UDP checksum ( in the correct order! )
2004
        test    eax, eax
-
 
2005
 
958
        mov     ax, [checkResult]
2006
        DEBUGF  1,"ptr=%x\n", eax
-
 
2007
        ret
-
 
2008
 
-
 
2009
  .error:
Line 959... Line -...
959
 
-
 
960
        ; If the UDP checksum computes to 0, we must make it 0xffff
-
 
961
        ; (0 is reserved for 'not used')
-
 
962
        test    ax, ax
-
 
963
        jnz     @f
2010
        DEBUGF  1,"not found\n", eax
964
        mov     ax, 0xffff
-
 
965
 
2011
        ret
Line -... Line 2012...
-
 
2012
 
-
 
2013
 
-
 
2014
;---------------------------------------------------
-
 
2015
;
-
 
2016
; SOCKET_ptr_to_num
966
    @@:
2017
;
-
 
2018
; Get socket number by its address
-
 
2019
;
-
 
2020
; IN:  eax = socket ptr
-
 
2021
; OUT: eax = 0 on error, socket num otherwise
-
 
2022
;       ZF = set on error
-
 
2023
;
-
 
2024
;---------------------------------------------------
-
 
2025
align 4
-
 
2026
SOCKET_ptr_to_num:
-
 
2027
 
-
 
2028
        DEBUGF  1,"SOCKET_ptr_to_num: ptr=%x ", eax
-
 
2029
 
-
 
2030
        call    SOCKET_check
-
 
2031
        jz      .error
-
 
2032
 
-
 
2033
        mov     eax, [eax + SOCKET.Number]
-
 
2034
 
-
 
2035
        DEBUGF  1,"num=%u\n", eax
-
 
2036
        ret
-
 
2037
 
-
 
2038
  .error:
-
 
2039
        DEBUGF  1,"not found\n", eax
-
 
2040
        ret
-
 
2041
 
-
 
2042
 
-
 
2043
;---------------------------------------------------
-
 
2044
;
-
 
2045
; SOCKET_check
-
 
2046
;
-
 
2047
; checks if the given value is really a socket ptr
-
 
2048
;
-
 
2049
; IN:  eax = socket ptr
-
 
2050
; OUT: eax = 0 on error, unchanged otherwise
-
 
2051
;       ZF = set on error
-
 
2052
;
-
 
2053
;---------------------------------------------------
-
 
2054
align 4
-
 
2055
SOCKET_check:
-
 
2056
 
-
 
2057
        DEBUGF  1,"SOCKET_check: %x\n", eax
-
 
2058
 
-
 
2059
        push    ebx
967
        xchg    al, ah
2060
        mov     ebx, net_sockets
-
 
2061
 
-
 
2062
  .next_socket:
-
 
2063
        mov     ebx, [ebx + SOCKET.NextPtr]
-
 
2064
        or      ebx, ebx
-
 
2065
        jz      .done
-
 
2066
        cmp     ebx, eax
-
 
2067
        jnz     .next_socket
-
 
2068
 
968
        mov     [edx + 20 + UDP_PACKET.Checksum], ax
2069
  .done:
-
 
2070
        mov     eax, ebx
-
 
2071
        test    eax, eax
-
 
2072
        pop     ebx
-
 
2073
 
-
 
2074
        ret
-
 
2075
 
-
 
2076
 
-
 
2077
 
-
 
2078
;---------------------------------------------------
-
 
2079
;
-
 
2080
; SOCKET_check_owner
-
 
2081
;
-
 
2082
; checks if the caller application owns the socket
-
 
2083
;
-
 
2084
; IN:  eax = socket ptr
969
 
2085
; OUT:  ZF = true/false
-
 
2086
;
-
 
2087
;---------------------------------------------------
-
 
2088
align 4
-
 
2089
SOCKET_check_owner:
-
 
2090
 
-
 
2091
        DEBUGF  1,"SOCKET_check_owner: %x\n", eax
-
 
2092
 
-
 
2093
        push    ebx
-
 
2094
        mov     ebx, [TASK_BASE]
-
 
2095
        mov     ebx, [ebx + TASKDATA.pid]
-
 
2096
        cmp     [eax + SOCKET.PID], ebx
-
 
2097
        pop      ebx
-
 
2098
 
-
 
2099
        ret
-
 
2100
 
-
 
2101
 
-
 
2102
 
-
 
2103
 
-
 
2104
;------------------------------------------------------
-
 
2105
;
-
 
2106
; SOCKET_process_end
-
 
2107
;
-
 
2108
; Kernel calls this function when a certain process ends
-
 
2109
; This function will check if the process had any open sockets
-
 
2110
; And update them accordingly
-
 
2111
;
Line 970... Line -...
970
        ; Fill in the IP header checksum
-
 
971
        GET_IHL ecx,edx              ; get IP-Header length
-
 
972
        stdcall checksum_jb, edx, ecx; buf_ptr, buf_size
2112
; IN:  edx = pid
Line -... Line 2113...
-
 
2113
; OUT: /
-
 
2114
;
-
 
2115
;------------------------------------------------------
-
 
2116
align 4
-
 
2117
SOCKET_process_end:
-
 
2118
 
-
 
2119
        DEBUGF  1, "SOCKET_process_end: %x\n", edx
973
        xchg    al, ah
2120
 
-
 
2121
        push    ebx
-
 
2122
        mov     ebx, net_sockets
-
 
2123
 
-
 
2124
  .next_socket:
-
 
2125
        mov     ebx, [ebx + SOCKET.NextPtr]
-
 
2126
  .next_socket_test:
-
 
2127
        test    ebx, ebx
-
 
2128
        jz      .done
974
        mov     [edx + IP_PACKET.HeaderChecksum], ax
2129
 
-
 
2130
        cmp     [ebx + SOCKET.PID], edx
975
 
2131
        jne     .next_socket
976
        ; Check destination IP address.
-