Subversion Repositories Kolibri OS

Rev

Rev 5594 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
3555 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5565 serge 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3555 Serge 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
9
;;     and Clevermouse.                                            ;;
10
;;                                                                 ;;
11
;;       Based on code by mike.dld                                 ;;
12
;;                                                                 ;;
13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
14
;;          Version 2, June 1991                                   ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
261 hidnplayr 17
 
593 mikedld 18
$Revision: 5984 $
19
 
2434 Serge 20
struct  SOCKET
3555 Serge 21
 
5984 serge 22
        NextPtr                 dd ?    ; pointer to next socket in list
23
        PrevPtr                 dd ?    ; pointer to previous socket in list
24
        Number                  dd ?    ; socket number
3555 Serge 25
 
26
        mutex                   MUTEX
27
 
5984 serge 28
        PID                     dd ?    ; process ID
29
        TID                     dd ?    ; thread ID
30
        Domain                  dd ?    ; INET4/INET6/LOCAL/..
31
        Type                    dd ?    ; RAW/STREAM/DGRAM
32
        Protocol                dd ?    ; UDP/TCP/ARP/ICMP
3555 Serge 33
        errorcode               dd ?
5984 serge 34
        device                  dd ?    ; device pointer, paired socket pointer if it's a local socket
3555 Serge 35
 
36
        options                 dd ?
37
        state                   dd ?
5984 serge 38
        backlog                 dw ?    ; number of incoming connections that can be queued
3555 Serge 39
 
40
        snd_proc                dd ?
41
        rcv_proc                dd ?
4265 Serge 42
        connect_proc            dd ?
3555 Serge 43
 
922 mikedld 44
ends
593 mikedld 45
 
3555 Serge 46
struct  IP_SOCKET               SOCKET
261 hidnplayr 47
 
5984 serge 48
        LocalIP                 rd 4    ; network byte order
49
        RemoteIP                rd 4    ; network byte order
50
        ttl                     db ?
51
                                rb 3    ; align
261 hidnplayr 52
 
3555 Serge 53
ends
54
 
55
struct  TCP_SOCKET              IP_SOCKET
56
 
5984 serge 57
        LocalPort               dw ?    ; network byte order
58
        RemotePort              dw ?    ; network byte order
3555 Serge 59
 
5984 serge 60
        t_state                 dd ?    ; TCB state
3555 Serge 61
        t_rxtshift              db ?
5984 serge 62
                                rb 3    ; align
3555 Serge 63
        t_rxtcur                dd ?
64
        t_dupacks               dd ?
65
        t_maxseg                dd ?
66
        t_force                 dd ?
67
        t_flags                 dd ?
68
 
69
;---------------
70
; RFC783 page 21
71
 
72
; send sequence
5984 serge 73
        SND_UNA                 dd ?    ; sequence number of unack'ed sent Packets
74
        SND_NXT                 dd ?    ; next send sequence number to use
75
        SND_UP                  dd ?    ; urgent pointer
76
        SND_WL1                 dd ?    ; window minus one
77
        SND_WL2                 dd ?    ;
78
        ISS                     dd ?    ; initial send sequence number
79
        SND_WND                 dd ?    ; send window
3555 Serge 80
 
81
; receive sequence
5984 serge 82
        RCV_WND                 dd ?    ; receive window
83
        RCV_NXT                 dd ?    ; next receive sequence number to use
84
        RCV_UP                  dd ?    ; urgent pointer
85
        IRS                     dd ?    ; initial receive sequence number
3555 Serge 86
 
87
;---------------------
88
; Additional variables
89
 
90
; receive variables
91
        RCV_ADV                 dd ?
92
 
93
; retransmit variables
94
        SND_MAX                 dd ?
95
 
96
; congestion control
4423 Serge 97
        SND_CWND                dd ?    ; congestion window
98
        SND_SSTHRESH            dd ?    ; slow start threshold
3555 Serge 99
 
100
;----------------------
101
; Transmit timing stuff
102
        t_idle                  dd ?
5565 serge 103
        t_rtt                   dd ?    ; round trip time
3555 Serge 104
        t_rtseq                 dd ?
5565 serge 105
        t_srtt                  dd ?    ; smoothed round trip time
3555 Serge 106
        t_rttvar                dd ?
107
        t_rttmin                dd ?
108
        max_sndwnd              dd ?
109
 
110
;-----------------
111
; Out-of-band data
112
        t_oobflags              dd ?
113
        t_iobc                  dd ?
114
        t_softerror             dd ?
115
 
116
 
117
;---------
118
; RFC 1323                              ; the order of next 4 elements may not change
119
 
120
        SND_SCALE               db ?
121
        RCV_SCALE               db ?
122
        requested_s_scale       db ?
123
        request_r_scale         db ?
124
 
125
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
126
        ts_recent_age           dd ?
127
        last_ack_sent           dd ?
128
 
129
 
130
;-------
131
; Timers
3626 Serge 132
        timer_flags             dd ?
5984 serge 133
        timer_retransmission    dd ?    ; rexmt
3555 Serge 134
        timer_persist           dd ?
5984 serge 135
        timer_keepalive         dd ?    ; keepalive/syn timeout
136
        timer_timed_wait        dd ?    ; also used as 2msl timer
4265 Serge 137
        timer_connect           dd ?
3555 Serge 138
 
139
; extra
140
 
5984 serge 141
        ts_ecr                  dd ?    ; timestamp echo reply
3555 Serge 142
        ts_val                  dd ?
143
 
5984 serge 144
        seg_next                dd ?    ; re-assembly queue
3555 Serge 145
 
146
ends
147
 
148
struct  UDP_SOCKET              IP_SOCKET
149
 
5984 serge 150
        LocalPort               dw ?    ; in network byte order
151
        RemotePort              dw ?    ; in network byte order
3555 Serge 152
 
153
ends
154
 
155
struct  RING_BUFFER
156
 
157
        mutex                   MUTEX
5984 serge 158
        start_ptr               dd ?    ; Pointer to start of buffer
159
        end_ptr                 dd ?    ; pointer to end of buffer
160
        read_ptr                dd ?    ; Read pointer
161
        write_ptr               dd ?    ; Write pointer
162
        size                    dd ?    ; Number of bytes buffered
3555 Serge 163
 
164
ends
165
 
166
struct  STREAM_SOCKET           TCP_SOCKET
167
 
168
        rcv                     RING_BUFFER
169
        snd                     RING_BUFFER
170
 
171
ends
172
 
173
struct  socket_queue_entry
174
 
175
        data_ptr                dd ?
5565 serge 176
        data_size               dd ?
3555 Serge 177
        buf_ptr                 dd ?
178
 
179
ends
180
 
5984 serge 181
struct  socket_options
3555 Serge 182
 
5984 serge 183
        level                   dd ?
184
        optname                 dd ?
185
        optlen                  dd ?
186
        optval                  dd ?
3555 Serge 187
 
5984 serge 188
ends
189
 
190
SOCKETBUFFSIZE          = 4096          ; in bytes
191
 
192
SOCKET_QUEUE_SIZE       = 10            ; maximum number of incoming packets queued for 1 socket
3555 Serge 193
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
194
SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
195
 
1154 clevermous 196
uglobal
3725 Serge 197
align 4
198
 
3555 Serge 199
        net_sockets     rd 4
200
        last_socket_num dd ?
5984 serge 201
        last_UDP_port   dw ?            ; last used ephemeral port
202
        last_TCP_port   dw ?            ;
3725 Serge 203
        socket_mutex    MUTEX
204
 
1154 clevermous 205
endg
206
 
3555 Serge 207
 
5984 serge 208
;-----------------------------------------------------------------;
209
;                                                                 ;
210
; SOCKET_init                                                     ;
211
;                                                                 ;
212
;-----------------------------------------------------------------;
3555 Serge 213
macro   SOCKET_init {
214
 
215
        xor     eax, eax
216
        mov     edi, net_sockets
217
        mov     ecx, 5
3725 Serge 218
        rep stosd
3555 Serge 219
 
220
       @@:
221
        pseudo_random eax
3626 Serge 222
        cmp     ax, EPHEMERAL_PORT_MIN
3555 Serge 223
        jb      @r
3626 Serge 224
        cmp     ax, EPHEMERAL_PORT_MAX
3555 Serge 225
        ja      @r
226
        xchg    al, ah
227
        mov     [last_UDP_port], ax
228
 
229
       @@:
230
        pseudo_random eax
3626 Serge 231
        cmp     ax, EPHEMERAL_PORT_MIN
3555 Serge 232
        jb      @r
3626 Serge 233
        cmp     ax, EPHEMERAL_PORT_MAX
3555 Serge 234
        ja      @r
235
        xchg    al, ah
236
        mov     [last_TCP_port], ax
237
 
3725 Serge 238
        mov     ecx, socket_mutex
239
        call    mutex_init
240
 
3555 Serge 241
}
242
 
5984 serge 243
;-----------------------------------------------------------------;
244
;                                                                 ;
245
; Sockets API (system function 75)                                ;
246
;                                                                 ;
247
;-----------------------------------------------------------------;
1154 clevermous 248
align 4
3555 Serge 249
sys_socket:
1154 clevermous 250
 
3725 Serge 251
        mov     dword[esp+20], 0        ; Set error code to 0
252
 
3555 Serge 253
        cmp     ebx, 255
254
        jz      SOCKET_debug
255
 
256
        cmp     ebx, .number
3725 Serge 257
        ja      .error
3555 Serge 258
        jmp     dword [.table + 4*ebx]
259
 
260
  .table:
5984 serge 261
        dd      SOCKET_open             ; 0
262
        dd      SOCKET_close            ; 1
263
        dd      SOCKET_bind             ; 2
264
        dd      SOCKET_listen           ; 3
265
        dd      SOCKET_connect          ; 4
266
        dd      SOCKET_accept           ; 5
267
        dd      SOCKET_send             ; 6
268
        dd      SOCKET_receive          ; 7
269
        dd      SOCKET_set_opt          ; 8
270
        dd      SOCKET_get_opt          ; 9
271
        dd      SOCKET_pair             ; 10
3555 Serge 272
  .number = ($ - .table) / 4 - 1
273
 
3725 Serge 274
  .error:
275
        mov     dword[esp+32], -1
276
        mov     dword[esp+20], EINVAL
3555 Serge 277
 
278
        ret
279
 
5984 serge 280
;-----------------------------------------------------------------;
281
;                                                                 ;
282
; SOCKET_open: Create a new socket.                               ;
283
;                                                                 ;
284
;   IN: ecx = domain                                              ;
285
;       edx = type                                                ;
286
;       esi = protocol                                            ;
287
;                                                                 ;
288
;  OUT: eax = socket number                                       ;
289
;       eax = -1 on error                                         ;
290
;       ebx = errorcode on error                                  ;
291
;                                                                 ;
292
;-----------------------------------------------------------------;
3555 Serge 293
align 4
294
SOCKET_open:
907 mikedld 295
 
3589 Serge 296
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
3555 Serge 297
 
298
        push    ecx edx esi
299
        call    SOCKET_alloc
300
        pop     esi edx ecx
5201 serge 301
        test    eax, eax
3725 Serge 302
        jz      .nobuffs
3555 Serge 303
 
5984 serge 304
        mov     [esp+32], edi           ; return socketnumber
3589 Serge 305
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
3555 Serge 306
 
3725 Serge 307
        test    edx, SO_NONBLOCK
308
        jz      @f
309
        or      [eax + SOCKET.options], SO_NONBLOCK
310
        and     edx, not SO_NONBLOCK
311
  @@:
3555 Serge 312
 
313
        mov     [eax + SOCKET.Domain], ecx
314
        mov     [eax + SOCKET.Type], edx
315
        mov     [eax + SOCKET.Protocol], esi
4265 Serge 316
        mov     [eax + SOCKET.connect_proc], connect_notsupp
3555 Serge 317
 
318
        cmp     ecx, AF_INET4
319
        jne     .no_inet4
320
 
5984 serge 321
        mov     [eax + IP_SOCKET.ttl], 128
322
 
3555 Serge 323
        cmp     edx, SOCK_DGRAM
324
        je      .udp
325
 
326
        cmp     edx, SOCK_STREAM
327
        je      .tcp
328
 
329
        cmp     edx, SOCK_RAW
330
        je      .raw
331
 
332
  .no_inet4:
333
        cmp     ecx, AF_PPP
334
        jne     .no_ppp
335
 
336
        cmp     esi, PPP_PROTO_ETHERNET
337
        je      .pppoe
338
 
339
  .no_ppp:
3725 Serge 340
  .unsupported:
341
        push    eax
342
        call    SOCKET_free
343
        pop     eax
344
        mov     dword[esp+20], EOPNOTSUPP
345
        mov     dword[esp+32], -1
3555 Serge 346
        ret
347
 
3725 Serge 348
  .nobuffs:
349
        mov     dword[esp+20], ENOBUFS
350
        mov     dword[esp+32], -1
351
        ret
352
 
3555 Serge 353
  .raw:
5984 serge 354
        test    esi, esi        ; IP_PROTO_IP
3725 Serge 355
        jz      .raw_ip
3555 Serge 356
 
357
        cmp     esi, IP_PROTO_ICMP
3725 Serge 358
        je      .raw_icmp
3555 Serge 359
 
3725 Serge 360
        jmp     .unsupported
3555 Serge 361
 
362
align 4
363
  .udp:
5984 serge 364
        push    eax
365
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
366
        pop     eax
367
 
3555 Serge 368
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
369
        mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
370
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
4265 Serge 371
        mov     [eax + SOCKET.connect_proc], UDP_connect
3555 Serge 372
        ret
373
 
374
align 4
375
  .tcp:
376
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
377
        mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
378
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
4265 Serge 379
        mov     [eax + SOCKET.connect_proc], TCP_connect
3555 Serge 380
 
381
        TCP_init_socket eax
382
        ret
383
 
384
 
385
align 4
3725 Serge 386
  .raw_ip:
5984 serge 387
        push    eax
388
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
389
        pop     eax
390
 
3555 Serge 391
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
392
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
4265 Serge 393
        mov     [eax + SOCKET.connect_proc], IPv4_connect
3555 Serge 394
        ret
395
 
396
 
397
align 4
3725 Serge 398
  .raw_icmp:
5984 serge 399
        push    eax
400
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
401
        pop     eax
402
 
3555 Serge 403
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
404
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
4265 Serge 405
        mov     [eax + SOCKET.connect_proc], IPv4_connect
3555 Serge 406
        ret
407
 
408
align 4
409
  .pppoe:
2434 Serge 410
        push    eax
3555 Serge 411
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
2434 Serge 412
        pop     eax
907 mikedld 413
 
3555 Serge 414
        mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
415
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
416
        ret
417
 
418
 
5984 serge 419
;-----------------------------------------------------------------;
420
;                                                                 ;
421
; SOCKET_bind: Bind to a local port.                              ;
422
;                                                                 ;
423
;   IN: ecx = socket number                                       ;
424
;       edx = pointer to sockaddr struct                          ;
425
;       esi = length of sockaddr struct                           ;
426
;                                                                 ;
427
;  OUT: eax = 0 on success                                        ;
428
;       eax = -1 on error                                         ;
429
;       ebx = errorcode on error                                  ;
430
;                                                                 ;
431
;-----------------------------------------------------------------;
3555 Serge 432
align 4
433
SOCKET_bind:
434
 
3589 Serge 435
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3555 Serge 436
 
437
        call    SOCKET_num_to_ptr
5984 serge 438
        test    eax, eax
3725 Serge 439
        jz      .invalid
3555 Serge 440
 
441
        cmp     esi, 2
3725 Serge 442
        jb      .invalid
3555 Serge 443
 
5984 serge 444
        cmp     [eax + UDP_SOCKET.LocalPort], 0 ; Socket can only be bound once
4265 Serge 445
        jnz     .invalid
446
 
3555 Serge 447
        cmp     word [edx], AF_INET4
448
        je      .af_inet4
449
 
450
        cmp     word [edx], AF_LOCAL
451
        je      .af_local
452
 
3725 Serge 453
  .notsupp:
454
        mov     dword[esp+20], EOPNOTSUPP
455
        mov     dword[esp+32], -1
456
        ret
3555 Serge 457
 
3725 Serge 458
  .invalid:
459
        mov     dword[esp+20], EINVAL
460
        mov     dword[esp+32], -1
461
        ret
462
 
3555 Serge 463
  .af_local:
464
        ; TODO: write code here
3725 Serge 465
        mov     dword[esp+32], 0
3555 Serge 466
        ret
467
 
468
  .af_inet4:
469
        cmp     esi, 6
3725 Serge 470
        jb      .invalid
3555 Serge 471
 
472
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
473
        je      .udp
474
 
475
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
476
        je      .tcp
477
 
3725 Serge 478
        jmp     .notsupp
3555 Serge 479
 
480
  .tcp:
481
  .udp:
482
 
4265 Serge 483
        pushd   [edx + 4]                       ; First, fill in the IP
484
        popd    [eax + IP_SOCKET.LocalIP]
3555 Serge 485
 
4265 Serge 486
        mov     bx, [edx + 2]                   ; Did caller specify a local port?
487
        test    bx, bx
488
        jnz     .just_check
489
        call    SOCKET_find_port                ; Nope, find an ephemeral one
490
        jmp     .done
491
 
492
  .just_check:
493
        call    SOCKET_check_port               ; Yes, check if it's still available
494
        jz      .addrinuse                      ; ZF is set by socket_check_port on error
495
 
496
  .done:
3589 Serge 497
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
3555 Serge 498
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
499
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
500
 
3725 Serge 501
        mov     dword[esp+32], 0
3555 Serge 502
        ret
503
 
3725 Serge 504
  .addrinuse:
505
        mov     dword[esp+32], -1
506
        mov     dword[esp+20], EADDRINUSE
507
        ret
3555 Serge 508
 
509
 
510
 
3725 Serge 511
 
5984 serge 512
;-----------------------------------------------------------------;
513
;                                                                 ;
514
; SOCKET_connect: Connect to the remote host.                     ;
515
;                                                                 ;
516
;   IN: ecx = socket number                                       ;
517
;       edx = pointer to sockaddr struct                          ;
518
;       esi = length of sockaddr struct                           ;
519
;                                                                 ;
520
;  OUT: eax = 0 on success                                        ;
521
;       eax = -1 on error                                         ;
522
;       ebx = errorcode on error                                  ;
523
;                                                                 ;
524
;-----------------------------------------------------------------;
3555 Serge 525
align 4
526
SOCKET_connect:
527
 
3589 Serge 528
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3555 Serge 529
 
530
        call    SOCKET_num_to_ptr
5984 serge 531
        test    eax, eax
3725 Serge 532
        jz      .invalid
3555 Serge 533
 
534
        cmp     esi, 8
3725 Serge 535
        jb      .invalid
3555 Serge 536
 
4265 Serge 537
        cmp     [eax + SOCKET.state], SS_ISCONNECTING
538
        je      .already
3555 Serge 539
 
4265 Serge 540
        test    [eax + SOCKET.options], SO_ACCEPTCON
541
        jnz     .notsupp
542
 
543
        call    [eax + SOCKET.connect_proc]
544
 
545
        mov     dword[esp+20], ebx
546
        mov     dword[esp+32], eax
547
        ret
548
 
549
 
3725 Serge 550
  .notsupp:
551
        mov     dword[esp+20], EOPNOTSUPP
552
        mov     dword[esp+32], -1
553
        ret
3555 Serge 554
 
3725 Serge 555
  .invalid:
556
        mov     dword[esp+20], EINVAL
557
        mov     dword[esp+32], -1
558
        ret
559
 
4265 Serge 560
  .already:
561
        mov     dword[esp+20], EALREADY
3725 Serge 562
        mov     dword[esp+32], -1
3555 Serge 563
        ret
564
 
3725 Serge 565
 
4265 Serge 566
connect_notsupp:
567
        xor     eax, eax
568
        dec     eax
569
        mov     ebx, EOPNOTSUPP
3725 Serge 570
        ret
571
 
572
 
5984 serge 573
;-----------------------------------------------------------------;
574
;                                                                 ;
575
; SOCKET_listen: Listen for incoming connections.                 ;
576
;                                                                 ;
577
;   IN: ecx = socket number                                       ;
578
;       edx = backlog in edx                                      ;
579
;                                                                 ;
580
;  OUT: eax = 0 on success                                        ;
581
;       eax = -1 on error                                         ;
582
;       ebx = errorcode on error                                  ;
583
;                                                                 ;
584
;-----------------------------------------------------------------;
3555 Serge 585
align 4
586
SOCKET_listen:
587
 
3589 Serge 588
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
3555 Serge 589
 
590
        call    SOCKET_num_to_ptr
5984 serge 591
        test    eax, eax
3725 Serge 592
        jz      .invalid
3555 Serge 593
 
594
        cmp     [eax + SOCKET.Domain], AF_INET4
3725 Serge 595
        jne     .notsupp
3555 Serge 596
 
597
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3725 Serge 598
        jne     .invalid
3555 Serge 599
 
600
        cmp     [eax + TCP_SOCKET.LocalPort], 0
3725 Serge 601
        je      .already
3555 Serge 602
 
603
        cmp     [eax + IP_SOCKET.LocalIP], 0
604
        jne     @f
3626 Serge 605
        push    [IP_LIST + 4]           ;;; fixme!!!!
3555 Serge 606
        pop     [eax + IP_SOCKET.LocalIP]
607
       @@:
608
 
609
        cmp     edx, MAX_backlog
610
        jbe     @f
611
        mov     edx, MAX_backlog
612
       @@:
613
 
614
        mov     [eax + SOCKET.backlog], dx
615
        or      [eax + SOCKET.options], SO_ACCEPTCON
616
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
617
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
618
 
619
        push    eax
620
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
621
        pop     eax
622
 
3725 Serge 623
        mov     dword[esp+32], 0
624
        ret
3555 Serge 625
 
3725 Serge 626
  .notsupp:
627
        mov     dword[esp+20], EOPNOTSUPP
628
        mov     dword[esp+32], -1
3555 Serge 629
        ret
630
 
3725 Serge 631
  .invalid:
632
        mov     dword[esp+20], EINVAL
633
        mov     dword[esp+32], -1
634
        ret
3555 Serge 635
 
3725 Serge 636
  .already:
637
        mov     dword[esp+20], EALREADY
638
        mov     dword[esp+32], -1
639
        ret
640
 
641
 
5984 serge 642
;-----------------------------------------------------------------;
643
;                                                                 ;
644
; SOCKET_accept: Accept an incoming connection.                   ;
645
;                                                                 ;
646
;   IN: ecx = socket number (of listening socket)                 ;
647
;       edx = ptr to sockaddr struct                              ;
648
;       esi = length of sockaddr struct                           ;
649
;                                                                 ;
650
;  OUT: eax = newly created socket num                            ;
651
;       eax = -1 on error                                         ;
652
;       ebx = errorcode on error                                  ;
653
;                                                                 ;
654
;-----------------------------------------------------------------;
3555 Serge 655
align 4
656
SOCKET_accept:
657
 
3589 Serge 658
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3555 Serge 659
 
660
        call    SOCKET_num_to_ptr
5984 serge 661
        test    eax, eax
3725 Serge 662
        jz      .invalid
3555 Serge 663
 
664
        test    [eax + SOCKET.options], SO_ACCEPTCON
3725 Serge 665
        jz      .invalid
3555 Serge 666
 
667
        cmp     [eax + SOCKET.Domain], AF_INET4
3725 Serge 668
        jne     .notsupp
3555 Serge 669
 
670
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3725 Serge 671
        jne     .invalid
3555 Serge 672
 
673
  .loop:
674
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
675
 
676
; Ok, we got a socket ptr
677
        mov     eax, [esi]
678
 
5984 serge 679
; Verify that it is (still) a valid socket
680
        call    SOCKET_check
681
        jz      .invalid
682
 
683
; Change sockets thread owner ID to that of the current thread
3555 Serge 684
        mov     ebx, [TASK_BASE]
685
        mov     ebx, [ebx + TASKDATA.pid]
686
        mov     [eax + SOCKET.TID], ebx
687
 
5984 serge 688
; Return socket number to caller
689
        mov     eax, [eax + SOCKET.Number]
3555 Serge 690
        mov     [esp+32], eax
691
        ret
692
 
693
  .block:
694
        test    [eax + SOCKET.options], SO_NONBLOCK
3725 Serge 695
        jnz     .wouldblock
3555 Serge 696
 
697
        call    SOCKET_block
698
        jmp     .loop
699
 
3725 Serge 700
  .wouldblock:
701
        mov     dword[esp+20], EWOULDBLOCK
702
        mov     dword[esp+32], -1
703
        ret
704
 
705
  .invalid:
706
        mov     dword[esp+20], EINVAL
707
        mov     dword[esp+32], -1
708
        ret
709
 
710
  .notsupp:
711
        mov     dword[esp+20], EOPNOTSUPP
712
        mov     dword[esp+32], -1
713
        ret
714
 
5984 serge 715
;-----------------------------------------------------------------;
716
;                                                                 ;
717
; SOCKET_close: Close the socket (and connection).                ;
718
;                                                                 ;
719
;   IN: ecx = socket number                                       ;
720
;                                                                 ;
721
;  OUT: eax = 0 on success                                        ;
722
;       eax = -1 on error                                         ;
723
;       ebx = errorcode on error                                  ;
724
;                                                                 ;
725
;-----------------------------------------------------------------;
3555 Serge 726
align 4
727
SOCKET_close:
728
 
3589 Serge 729
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
3555 Serge 730
 
731
        call    SOCKET_num_to_ptr
5984 serge 732
        test    eax, eax
3725 Serge 733
        jz      .invalid
3555 Serge 734
 
3725 Serge 735
        mov     dword[esp+32], 0                                ; The socket exists, so we will succeed in closing it.
3555 Serge 736
 
737
        or      [eax + SOCKET.options], SO_NONBLOCK             ; Mark the socket as non blocking, we dont want it to block any longer!
738
 
739
        test    [eax + SOCKET.state], SS_BLOCKED                ; Is the socket still in blocked state?
2434 Serge 740
        jz      @f
5201 serge 741
        call    SOCKET_notify                                   ; Unblock it.
3555 Serge 742
  @@:
907 mikedld 743
 
3555 Serge 744
        cmp     [eax + SOCKET.Domain], AF_INET4
745
        jne     .free
746
 
747
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
748
        je      .tcp
749
 
750
  .free:
751
        call    SOCKET_free
752
        ret
753
 
754
  .tcp:
755
        call    TCP_usrclosed
756
 
4423 Serge 757
        test    eax, eax
758
        jz      @f
759
        call    TCP_output                                      ; If connection is not closed yet, send the FIN
760
  @@:
3555 Serge 761
        ret
762
 
763
 
3725 Serge 764
  .invalid:
765
        mov     dword[esp+20], EINVAL
766
        mov     dword[esp+32], -1
767
        ret
768
 
769
 
5984 serge 770
;-----------------------------------------------------------------;
771
;                                                                 ;
772
; SOCKET_receive: Receive some data from the remote end.          ;
773
;                                                                 ;
774
;   IN: ecx = socket number                                       ;
775
;       edx = addr to application buffer                          ;
776
;       edx = length of application buffer                        ;
777
;       edi = flags                                               ;
778
;                                                                 ;
779
;  OUT: eax = number of bytes copied                              ;
780
;       eax = -1 on error                                         ;
781
;       eax = 0 when socket has been closed by the remote end     ;
782
;       ebx = errorcode on error                                  ;
783
;                                                                 ;
784
;-----------------------------------------------------------------;
3555 Serge 785
align 4
786
SOCKET_receive:
787
 
3589 Serge 788
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
3555 Serge 789
 
790
        call    SOCKET_num_to_ptr
5984 serge 791
        test    eax, eax
3725 Serge 792
        jz      .invalid
3555 Serge 793
 
3725 Serge 794
  .loop:
795
        push    edi
3589 Serge 796
        call    [eax + SOCKET.rcv_proc]
3725 Serge 797
        pop     edi
3555 Serge 798
 
4265 Serge 799
        test    [eax + SOCKET.state], SS_CANTRCVMORE
5565 serge 800
        jnz     .last_data
4265 Serge 801
 
3725 Serge 802
        cmp     ebx, EWOULDBLOCK
803
        jne     .return
804
 
805
        test    edi, MSG_DONTWAIT
806
        jnz     .return_err
807
 
5984 serge 808
        test    [eax + SOCKET.options], SO_NONBLOCK
809
        jnz     .return_err
3725 Serge 810
 
811
        call    SOCKET_block
812
        jmp     .loop
813
 
814
 
815
  .invalid:
816
        push    EINVAL
817
        pop     ebx
818
  .return_err:
4265 Serge 819
        mov     ecx, -1
3725 Serge 820
  .return:
821
        mov     [esp+20], ebx
4265 Serge 822
        mov     [esp+32], ecx
3589 Serge 823
        ret
3555 Serge 824
 
5565 serge 825
  .last_data:
826
        test    ecx, ecx
827
        jz      .return
5984 serge 828
        call    SOCKET_notify                                   ; Call me again!
5565 serge 829
        jmp     .return
3589 Serge 830
 
3725 Serge 831
 
832
 
833
 
3555 Serge 834
align 4
835
SOCKET_receive_dgram:
836
 
3589 Serge 837
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3555 Serge 838
 
5984 serge 839
        test    edi, MSG_PEEK
840
        jnz     .peek
3555 Serge 841
 
5984 serge 842
        mov     ebx, esi                                        ; buffer length
843
 
3725 Serge 844
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success.
3555 Serge 845
        mov     ecx, [esi + socket_queue_entry.data_size]
3589 Serge 846
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3555 Serge 847
 
3725 Serge 848
        cmp     ecx, ebx                                        ; If data segment does not fit in applications buffer, abort
3555 Serge 849
        ja      .too_small
850
 
4265 Serge 851
        push    eax ecx
3555 Serge 852
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
853
        mov     esi, [esi + socket_queue_entry.data_ptr]
3589 Serge 854
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3555 Serge 855
 
3725 Serge 856
; copy the data from kernel buffer to application buffer
857
        mov     edi, edx                                        ; bufferaddr
3555 Serge 858
        shr     ecx, 1
859
        jnc     .nb
860
        movsb
861
  .nb:
862
        shr     ecx, 1
863
        jnc     .nw
864
        movsw
865
  .nw:
866
        test    ecx, ecx
867
        jz      .nd
3725 Serge 868
        rep movsd
3555 Serge 869
  .nd:
870
 
5565 serge 871
        call    NET_BUFF_free
4265 Serge 872
        pop     ecx eax                                         ; return number of bytes copied to application
5984 serge 873
        cmp     [eax + SOCKET_QUEUE_LOCATION + queue.size], 0
874
        je      @f
875
        call    SOCKET_notify                                   ; Queue another network event
876
  @@:
877
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
3555 Serge 878
        ret
879
 
880
  .too_small:
4265 Serge 881
        mov     ecx, -1
3725 Serge 882
        push    EMSGSIZE
883
        pop     ebx
3589 Serge 884
        ret
3555 Serge 885
 
3725 Serge 886
  .wouldblock:
887
        push    EWOULDBLOCK
888
        pop     ebx
889
        ret
3555 Serge 890
 
5984 serge 891
  .peek:
892
        xor     ebx, ebx
893
        xor     ecx, ecx
894
        cmp     [eax + SOCKET_QUEUE_LOCATION + queue.size], 0
895
        je      @f
896
        mov     esi, [eax + SOCKET_QUEUE_LOCATION + queue.r_ptr]
897
        mov     ecx, [esi + socket_queue_entry.data_size]
898
  @@:
899
        ret
3555 Serge 900
 
901
 
902
align 4
903
SOCKET_receive_local:
904
 
905
        ; does this socket have a PID yet?
906
        cmp     [eax + SOCKET.PID], 0
907
        jne     @f
908
 
909
        ; Change PID to that of current process
2434 Serge 910
        mov     ebx, [TASK_BASE]
911
        mov     ebx, [ebx + TASKDATA.pid]
912
        mov     [eax + SOCKET.PID], ebx
3725 Serge 913
        mov     [eax + SOCKET.TID], ebx                         ; currently TID = PID in kolibrios :(
3555 Serge 914
      @@:
907 mikedld 915
 
3555 Serge 916
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
922 mikedld 917
 
3725 Serge 918
; ... continue to SOCKET_receive_stream
919
 
3555 Serge 920
align 4
921
SOCKET_receive_stream:
922 mikedld 922
 
3589 Serge 923
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3555 Serge 924
 
3725 Serge 925
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
926
        je      .wouldblock
927
 
928
        test    edi, MSG_PEEK
929
        jnz     .peek
930
 
3555 Serge 931
        mov     ecx, esi
932
        mov     edi, edx
933
        xor     edx, edx
934
 
4265 Serge 935
        push    eax
3555 Serge 936
        add     eax, STREAM_SOCKET.rcv
3725 Serge 937
        call    SOCKET_ring_read                                ; copy data from kernel buffer to application buffer
938
        call    SOCKET_ring_free                                ; free read memory
4265 Serge 939
        pop     eax
3555 Serge 940
 
5565 serge 941
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
942
        jne     .more_data
3725 Serge 943
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
2434 Serge 944
        ret
907 mikedld 945
 
5565 serge 946
  .more_data:
947
        call    SOCKET_notify                                   ; Queue another network event
948
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
949
        ret
950
 
3725 Serge 951
  .wouldblock:
952
        push    EWOULDBLOCK
953
        pop     ebx
4265 Serge 954
        xor     ecx, ecx
3725 Serge 955
        ret
956
 
3555 Serge 957
  .peek:
4265 Serge 958
        mov     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
3725 Serge 959
        xor     ebx, ebx
3555 Serge 960
        ret
961
 
962
 
5984 serge 963
;-----------------------------------------------------------------;
964
;                                                                 ;
965
; SOCKET_send: Send some data to the remote end.                  ;
966
;                                                                 ;
967
;   IN: ecx = socket number                                       ;
968
;       edx = pointer to data                                     ;
969
;       esi = data length                                         ;
970
;       edi = flags                                               ;
971
;                                                                 ;
972
;  OUT: eax = number of bytes sent                                ;
973
;       eax = -1 on error                                         ;
974
;       ebx = errorcode on error                                  ;
975
;                                                                 ;
976
;-----------------------------------------------------------------;
3555 Serge 977
align 4
978
SOCKET_send:
907 mikedld 979
 
3589 Serge 980
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
907 mikedld 981
 
3555 Serge 982
        call    SOCKET_num_to_ptr
5984 serge 983
        test    eax, eax
3725 Serge 984
        jz      .invalid
3555 Serge 985
 
986
        mov     ecx, esi
987
        mov     esi, edx
988
 
989
        jmp     [eax + SOCKET.snd_proc]
990
 
3725 Serge 991
  .invalid:
992
        mov     dword[esp+20], EINVAL
993
        mov     dword[esp+32], -1
994
        ret
3555 Serge 995
 
3725 Serge 996
 
3555 Serge 997
align 4
998
SOCKET_send_udp:
999
 
3589 Serge 1000
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3555 Serge 1001
 
1002
        mov     [esp+32], ecx
1003
        call    UDP_output
1004
        cmp     eax, -1
3725 Serge 1005
        je      .error
3555 Serge 1006
        ret
1007
 
3725 Serge 1008
  .error:
1009
        mov     dword[esp+32], -1
1010
        mov     dword[esp+20], EMSGSIZE ; FIXME: UDP_output should return error codes!
1011
        ret
3555 Serge 1012
 
3725 Serge 1013
 
3555 Serge 1014
align 4
1015
SOCKET_send_tcp:
1016
 
3589 Serge 1017
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3555 Serge 1018
 
2434 Serge 1019
        push    eax
3555 Serge 1020
        add     eax, STREAM_SOCKET.snd
1021
        call    SOCKET_ring_write
2434 Serge 1022
        pop     eax
907 mikedld 1023
 
3555 Serge 1024
        mov     [esp+32], ecx
3725 Serge 1025
        mov     [eax + SOCKET.errorcode], 0
1026
        push    eax
1027
        call    TCP_output              ; FIXME: this doesnt look pretty, does it?
1028
        pop     eax
1029
        mov     eax, [eax + SOCKET.errorcode]
1030
        mov     [esp+20], eax
2434 Serge 1031
        ret
907 mikedld 1032
 
3555 Serge 1033
 
1034
align 4
1035
SOCKET_send_ip:
1036
 
3589 Serge 1037
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3555 Serge 1038
 
1039
        mov     [esp+32], ecx
5984 serge 1040
        call    IPv4_output_raw
3555 Serge 1041
        cmp     eax, -1
3725 Serge 1042
        je      .error
2434 Serge 1043
        ret
907 mikedld 1044
 
3725 Serge 1045
  .error:
5984 serge 1046
        mov     dword[esp+32], eax
1047
        mov     dword[esp+20], ebx
3725 Serge 1048
        ret
3555 Serge 1049
 
3725 Serge 1050
 
3555 Serge 1051
align 4
1052
SOCKET_send_icmp:
1053
 
3589 Serge 1054
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3555 Serge 1055
 
1056
        mov     [esp+32], ecx
5984 serge 1057
        call    ICMP_output_raw
3555 Serge 1058
        cmp     eax, -1
3725 Serge 1059
        je      .error
3555 Serge 1060
        ret
1061
 
3725 Serge 1062
  .error:
5984 serge 1063
        mov     dword[esp+32], eax
1064
        mov     dword[esp+20], ebx
3725 Serge 1065
        ret
3555 Serge 1066
 
3725 Serge 1067
 
3555 Serge 1068
align 4
1069
SOCKET_send_pppoe:
1070
 
3589 Serge 1071
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
3555 Serge 1072
 
1073
        mov     [esp+32], ecx
1074
        mov     ebx, [eax + SOCKET.device]
1075
 
3725 Serge 1076
        call    PPPoE_discovery_output  ; FIXME: errorcodes
3555 Serge 1077
        cmp     eax, -1
3725 Serge 1078
        je      .error
3555 Serge 1079
        ret
1080
 
3725 Serge 1081
  .error:
1082
        mov     dword[esp+32], -1
1083
        mov     dword[esp+20], EMSGSIZE
1084
        ret
3555 Serge 1085
 
1086
 
3725 Serge 1087
 
3555 Serge 1088
align 4
1089
SOCKET_send_local:
1090
 
1091
        ; does this socket have a PID yet?
1092
        cmp     [eax + SOCKET.PID], 0
1093
        jne     @f
1094
 
1095
        ; Change PID to that of current process
1096
        mov     ebx, [TASK_BASE]
1097
        mov     ebx, [ebx + TASKDATA.pid]
1098
        mov     [eax + SOCKET.PID], ebx
1099
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1100
      @@:
1101
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local_
1102
 
1103
align 4
1104
SOCKET_send_local_:
1105
 
3589 Serge 1106
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3555 Serge 1107
 
1108
        ; get the other side's socket and check if it still exists
1109
        mov     eax, [eax + SOCKET.device]
1110
        call    SOCKET_check
3725 Serge 1111
        jz      .invalid
3555 Serge 1112
 
1113
        ; allright, shove in the data!
1114
        push    eax
1115
        add     eax, STREAM_SOCKET.rcv
1116
        call    SOCKET_ring_write
1117
        pop     eax
1118
 
1119
        ; return the number of written bytes (or errorcode) to application
1120
        mov     [esp+32], ecx
1121
 
1122
        ; and notify the other end
1123
        call    SOCKET_notify
1124
 
1125
        ret
1126
 
3725 Serge 1127
  .invalid:
1128
        mov     dword[esp+32], -1
1129
        mov     dword[esp+20], EINVAL
1130
        ret
3555 Serge 1131
 
3725 Serge 1132
 
5984 serge 1133
;-----------------------------------------------------------------;
1134
;                                                                 ;
1135
; SOCKET_get_options: Read a socket option                        ;
1136
;                                                                 ;
1137
;   IN: ecx = socket number                                       ;
1138
;       edx = pointer to socket options struct                    ;
1139
;                                                                 ;
1140
;  OUT: eax = 0 on success                                        ;
1141
;       eax = -1 on error                                         ;
1142
;       ebx = errorcode on error                                  ;
1143
;                                                                 ;
1144
;-----------------------------------------------------------------;
1145
align 4
1146
SOCKET_get_opt:
1147
 
1148
; FIXME:
3555 Serge 1149
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
1150
; TODO: find best way to notify that send()'ed data were acknowledged
1151
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
922 mikedld 1152
 
3589 Serge 1153
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
922 mikedld 1154
 
3555 Serge 1155
        call    SOCKET_num_to_ptr
5984 serge 1156
        test    eax, eax
3725 Serge 1157
        jz      .invalid
3555 Serge 1158
 
1159
        cmp     dword [edx], IP_PROTO_TCP
3725 Serge 1160
        jne     .invalid
3555 Serge 1161
        cmp     dword [edx+4], -2
1162
        je      @f
1163
        cmp     dword [edx+4], -3
3725 Serge 1164
        jne     .invalid
3555 Serge 1165
@@:
1166
;        mov     eax, [edx+12]
1167
;        test    eax, eax
1168
;        jz      .fail
1169
;        cmp     dword [eax], 4
1170
;        mov     dword [eax], 4
1171
;        jb      .fail
1172
;        stdcall net_socket_num_to_addr, ecx
1173
;        test    eax, eax
1174
;        jz      .fail
1175
;        ; todo: check that eax is really TCP socket
1176
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
1177
;        cmp     dword [edx+4], -2
1178
;        jz      @f
1179
;        mov     ecx, [eax + TCP_SOCKET.state]
1180
@@:
1181
        mov     eax, [edx+8]
1182
        test    eax, eax
1183
        jz      @f
1184
        mov     [eax], ecx
1185
@@:
1186
        mov     dword [esp+32], 0
2434 Serge 1187
        ret
907 mikedld 1188
 
3725 Serge 1189
  .invalid:
1190
        mov     dword[esp+32], -1
1191
        mov     dword[esp+20], EINVAL
1192
        ret
3555 Serge 1193
 
1194
 
5984 serge 1195
;-----------------------------------------------------------------;
1196
;                                                                 ;
1197
; SOCKET_set_options: Set a socket option.                        ;
1198
;                                                                 ;
1199
;   IN: ecx = socket number                                       ;
1200
;       edx = pointer to socket options struct                    ;
1201
;                                                                 ;
1202
;  OUT: eax = 0 on success                                        ;
1203
;       eax = -1 on error                                         ;
1204
;       ebx = errorcode on error                                  ;
1205
;                                                                 ;
1206
;-----------------------------------------------------------------;
3555 Serge 1207
align 4
1208
SOCKET_set_opt:
1209
 
3589 Serge 1210
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3555 Serge 1211
 
1212
        call    SOCKET_num_to_ptr
5984 serge 1213
        test    eax, eax
3725 Serge 1214
        jz      .invalid
3555 Serge 1215
 
5984 serge 1216
        cmp     [edx + socket_options.level], IP_PROTO_IP
1217
        je      .ip
1218
        cmp     [edx + socket_options.level], SOL_SOCKET
3725 Serge 1219
        jne     .invalid
3555 Serge 1220
 
5984 serge 1221
  .socket:
1222
        cmp     [edx + socket_options.optname], SO_BINDTODEVICE
1223
        jne     .invalid
3555 Serge 1224
 
1225
  .bind:
5984 serge 1226
        cmp     [edx + socket_options.optlen], 0
3555 Serge 1227
        je      .unbind
1228
 
5984 serge 1229
        movzx   edx, byte[edx + socket_options.optval]
3626 Serge 1230
        cmp     edx, NET_DEVICES_MAX
3725 Serge 1231
        ja      .invalid
3555 Serge 1232
 
1233
        mov     edx, [NET_DRV_LIST + 4*edx]
1234
        test    edx, edx
3725 Serge 1235
        jz      .already
3555 Serge 1236
        mov     [eax + SOCKET.device], edx
1237
 
5594 serge 1238
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n", eax, edx
3555 Serge 1239
 
3725 Serge 1240
        mov     dword[esp+32], 0        ; success!
2434 Serge 1241
        ret
907 mikedld 1242
 
3555 Serge 1243
  .unbind:
1244
        mov     [eax + SOCKET.device], 0
1245
 
3725 Serge 1246
        mov     dword[esp+32], 0        ; success!
3555 Serge 1247
        ret
1248
 
5984 serge 1249
  .ip:
1250
        cmp     [edx + socket_options.optname], IP_TTL
1251
        jne     .invalid
1252
 
1253
  .ttl:
1254
        mov     bl, byte[edx + socket_options.optval]
1255
        mov     [eax + IP_SOCKET.ttl], bl
1256
 
1257
        mov     dword[esp+32], 0        ; success!
1258
        ret
1259
 
3725 Serge 1260
  .already:
1261
        mov     dword[esp+20], EALREADY
1262
        mov     dword[esp+32], -1
3555 Serge 1263
        ret
1264
 
5984 serge 1265
  .invalid:
1266
        mov     dword[esp+20], EINVAL
1267
        mov     dword[esp+32], -1
1268
        ret
3555 Serge 1269
 
1270
 
1271
 
5984 serge 1272
 
1273
;-----------------------------------------------------------------;
1274
;                                                                 ;
1275
; SOCKET_pair: Allocate a pair of linked local sockets.           ;
1276
;                                                                 ;
1277
;  IN: /                                                          ;
1278
;                                                                 ;
1279
; OUT: eax = socket1 num on success                               ;
1280
;      eax = -1 on error                                          ;
1281
;      ebx = socket2 num on success                               ;
1282
;      ebx = errorcode on error                                   ;
1283
;                                                                 ;
1284
;-----------------------------------------------------------------;
3555 Serge 1285
align 4
1286
SOCKET_pair:
922 mikedld 1287
 
3589 Serge 1288
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3555 Serge 1289
 
1290
        call    SOCKET_alloc
5201 serge 1291
        test    eax, eax
3725 Serge 1292
        jz      .nomem1
3555 Serge 1293
        mov     [esp+32], edi   ; application's eax
1294
 
1295
        mov     [eax + SOCKET.Domain], AF_LOCAL
1296
        mov     [eax + SOCKET.Type], SOCK_STREAM
1297
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1298
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1299
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1300
        mov     [eax + SOCKET.PID], 0
1301
        mov     ebx, eax
1302
 
1303
        call    SOCKET_alloc
5201 serge 1304
        test    eax, eax
3725 Serge 1305
        jz      .nomem2
1306
        mov     [esp+20], edi   ; application's ebx
922 mikedld 1307
 
3555 Serge 1308
        mov     [eax + SOCKET.Domain], AF_LOCAL
1309
        mov     [eax + SOCKET.Type], SOCK_STREAM
1310
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
1311
        mov     [eax + SOCKET.snd_proc], SOCKET_send_local
1312
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_local
1313
        mov     [eax + SOCKET.PID], 0
1314
 
1315
        ; Link the two sockets to eachother
1316
        mov     [eax + SOCKET.device], ebx
1317
        mov     [ebx + SOCKET.device], eax
1318
 
1319
        lea     eax, [eax + STREAM_SOCKET.rcv]
1320
        call    SOCKET_ring_create
5201 serge 1321
        test    eax, eax
5984 serge 1322
        jz      .nomem2
3555 Serge 1323
 
1324
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1325
        call    SOCKET_ring_create
5201 serge 1326
        test    eax, eax
1327
        jz      .nomem2
3555 Serge 1328
 
2434 Serge 1329
        ret
907 mikedld 1330
 
3725 Serge 1331
  .nomem2:
5984 serge 1332
        mov     eax, [esp+20]
3555 Serge 1333
        call    SOCKET_free
5984 serge 1334
 
3725 Serge 1335
  .nomem1:
5984 serge 1336
        mov     eax, [esp+32]
1337
        call    SOCKET_free
1338
 
3725 Serge 1339
        mov     dword[esp+32], -1
5984 serge 1340
        mov     dword[esp+20], ENOMEM
3725 Serge 1341
        ret
907 mikedld 1342
 
3555 Serge 1343
 
1344
 
5984 serge 1345
;-----------------------------------------------------------------;
1346
;                                                                 ;
1347
; SOCKET_debug: Copy socket variables to application buffer.      ;
1348
;                                                                 ;
1349
;   IN: ecx = socket number                                       ;
1350
;       edx = pointer to application buffer                       ;
1351
;                                                                 ;
1352
;  OUT: eax = 0 on success                                        ;
1353
;       eax = -1 on error                                         ;
1354
;       ebx = errorcode on error                                  ;
1355
;                                                                 ;
1356
;-----------------------------------------------------------------;
3555 Serge 1357
align 4
1358
SOCKET_debug:
1359
 
3589 Serge 1360
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3555 Serge 1361
 
1362
        mov     edi, edx
1363
 
1364
        test    ecx, ecx
1365
        jz      .returnall
1366
 
1367
        call    SOCKET_num_to_ptr
5984 serge 1368
        test    eax, eax
3725 Serge 1369
        jz      .invalid
3555 Serge 1370
 
1371
        mov     esi, eax
1372
        mov     ecx, SOCKETBUFFSIZE/4
3725 Serge 1373
        rep movsd
3555 Serge 1374
 
3725 Serge 1375
        mov     dword[esp+32], 0
2434 Serge 1376
        ret
261 hidnplayr 1377
 
3555 Serge 1378
  .returnall:
1379
        mov     ebx, net_sockets
1380
  .next_socket:
1381
        mov     ebx, [ebx + SOCKET.NextPtr]
2434 Serge 1382
        test    ebx, ebx
3555 Serge 1383
        jz      .done
1384
        mov     eax, [ebx + SOCKET.Number]
1385
        stosd
1386
        jmp     .next_socket
1387
  .done:
1388
        xor     eax, eax
1389
        stosd
3725 Serge 1390
        mov     dword[esp+32], eax
1391
        ret
3555 Serge 1392
 
3725 Serge 1393
  .invalid:
1394
        mov     dword[esp+32], -1
5984 serge 1395
        mov     dword[esp+20], EINVAL
2434 Serge 1396
        ret
1154 clevermous 1397
 
3555 Serge 1398
 
5984 serge 1399
;-----------------------------------------------------------------;
1400
;   ____                                                 ____     ;
1401
;   \  /              End of sockets API                 \  /     ;
1402
;    \/                                                   \/      ;
1403
;    ()        Internally used functions follow           ()      ;
1404
;                                                                 ;
1405
;-----------------------------------------------------------------;
1406
 
1407
 
1408
;-----------------------------------------------------------------;
1409
;                                                                 ;
1410
; SOCKET_find_port:                                               ;
1411
; Fill in the local port number for TCP and UDP sockets           ;
1412
; This procedure always works because the number of sockets is    ;
1413
; limited to a smaller number then the number of possible ports   ;
1414
;                                                                 ;
1415
;  IN:  eax = socket pointer                                      ;
1416
;                                                                 ;
1417
;  OUT: /                                                         ;
1418
;                                                                 ;
1419
;-----------------------------------------------------------------;
3555 Serge 1420
align 4
1421
SOCKET_find_port:
261 hidnplayr 1422
 
3589 Serge 1423
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
261 hidnplayr 1424
 
3555 Serge 1425
        push    ebx esi ecx
261 hidnplayr 1426
 
3555 Serge 1427
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1428
        je      .udp
261 hidnplayr 1429
 
3555 Serge 1430
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1431
        je      .tcp
1432
 
1433
        pop     ecx esi ebx
2434 Serge 1434
        ret
261 hidnplayr 1435
 
3555 Serge 1436
  .udp:
1437
        mov     bx, [last_UDP_port]
1438
        call    .findit
1439
        mov     [last_UDP_port], bx
1154 clevermous 1440
 
3555 Serge 1441
        pop     ecx esi ebx
2434 Serge 1442
        ret
261 hidnplayr 1443
 
3555 Serge 1444
  .tcp:
1445
        mov     bx, [last_TCP_port]
1446
        call    .findit
1447
        mov     [last_TCP_port], bx
1448
 
1449
        pop     ecx esi ebx
1450
        ret
1451
 
1452
 
1453
  .restart:
1454
        mov     bx, MIN_EPHEMERAL_PORT_N
1455
  .findit:
1456
        cmp     bx, MAX_EPHEMERAL_PORT_N
1457
        je      .restart
1458
 
1459
        add     bh, 1
1460
        adc     bl, 0
1461
 
1462
        call    SOCKET_check_port
1463
        jz      .findit
1464
        ret
1465
 
1466
 
1467
 
5984 serge 1468
;-----------------------------------------------------------------;
1469
;                                                                 ;
1470
; SOCKET_check_port (to be used with AF_INET only!)               ;
1471
;                                                                 ;
1472
; Checks if a local port number is unused                         ;
1473
; If the proposed port number is unused, it is filled in in the   ;
1474
; socket structure                                                ;
1475
;                                                                 ;
1476
;   IN: eax = socket ptr                                          ;
1477
;       bx = proposed socket number (network byte order)          ;
1478
;                                                                 ;
1479
;  OUT: ZF = set on error                                         ;
1480
;                                                                 ;
1481
;-----------------------------------------------------------------;
3555 Serge 1482
align 4
1483
SOCKET_check_port:
261 hidnplayr 1484
 
3589 Serge 1485
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
261 hidnplayr 1486
 
3725 Serge 1487
        pusha
1488
        mov     ecx, socket_mutex
1489
        call    mutex_lock
1490
        popa
1491
 
3555 Serge 1492
        mov     ecx, [eax + SOCKET.Protocol]
1493
        mov     edx, [eax + IP_SOCKET.LocalIP]
1494
        mov     esi, net_sockets
261 hidnplayr 1495
 
907 mikedld 1496
  .next_socket:
3555 Serge 1497
        mov     esi, [esi + SOCKET.NextPtr]
1498
        or      esi, esi
1499
        jz      .port_ok
1500
 
1501
        cmp     [esi + SOCKET.Protocol], ecx
2434 Serge 1502
        jne     .next_socket
3555 Serge 1503
 
1504
        cmp     [esi + IP_SOCKET.LocalIP], edx
2434 Serge 1505
        jne     .next_socket
261 hidnplayr 1506
 
3555 Serge 1507
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1508
        jne     .next_socket
261 hidnplayr 1509
 
3725 Serge 1510
        pusha
1511
        mov     ecx, socket_mutex
1512
        call    mutex_unlock
1513
        popa
1514
 
3589 Serge 1515
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
3555 Serge 1516
        ret
261 hidnplayr 1517
 
3555 Serge 1518
  .port_ok:
3725 Serge 1519
        pusha
1520
        mov     ecx, socket_mutex
1521
        call    mutex_unlock
1522
        popa
1523
 
3589 Serge 1524
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3555 Serge 1525
        mov     [eax + UDP_SOCKET.LocalPort], bx
1526
        or      bx, bx                                  ; clear the zero-flag
1527
        ret
261 hidnplayr 1528
 
1529
 
1530
 
5984 serge 1531
;-----------------------------------------------------------------;
1532
;                                                                 ;
1533
; SOCKET_input: Update a (stateless) socket with received data.   ;
1534
;                                                                 ;
1535
; Note: The socket's mutex should already be set !                ;
1536
;                                                                 ;
1537
;   IN: eax = socket ptr                                          ;
1538
;       ecx = data size                                           ;
1539
;       esi = ptr to data                                         ;
1540
;       [esp] = ptr to buf                                        ;
1541
;                                                                 ;
1542
;  OUT: /                                                         ;
1543
;                                                                 ;
1544
;-----------------------------------------------------------------;
3555 Serge 1545
align 4
1546
SOCKET_input:
261 hidnplayr 1547
 
3589 Serge 1548
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
261 hidnplayr 1549
 
5565 serge 1550
        push    ecx
3555 Serge 1551
        push    esi
1552
        mov     esi, esp
261 hidnplayr 1553
 
3555 Serge 1554
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
261 hidnplayr 1555
 
3589 Serge 1556
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3555 Serge 1557
        add     esp, sizeof.socket_queue_entry
261 hidnplayr 1558
 
3555 Serge 1559
        pusha
1560
        lea     ecx, [eax + SOCKET.mutex]
1561
        call    mutex_unlock
1562
        popa
261 hidnplayr 1563
 
3555 Serge 1564
        jmp     SOCKET_notify
261 hidnplayr 1565
 
3555 Serge 1566
  .full:
3589 Serge 1567
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
261 hidnplayr 1568
 
3555 Serge 1569
        pusha
1570
        lea     ecx, [eax + SOCKET.mutex]
1571
        call    mutex_unlock
1572
        popa
261 hidnplayr 1573
 
5984 serge 1574
        add     esp, 8
5565 serge 1575
        call    NET_BUFF_free
2434 Serge 1576
        ret
261 hidnplayr 1577
 
1154 clevermous 1578
 
5984 serge 1579
;-----------------------------------------------------------------;
1580
;                                                                 ;
1581
; SOCKET_ring_create: Create a ringbuffer for sockets.            ;
1582
;                                                                 ;
1583
;   IN: eax = ptr to ring struct                                  ;
1584
;                                                                 ;
1585
;  OUT: eax = 0 on error                                          ;
1586
;       eax = start ptr                                           ;
1587
;                                                                 ;
1588
;-----------------------------------------------------------------;
3555 Serge 1589
align 4
1590
SOCKET_ring_create:
1591
 
1592
        push    esi
1593
        mov     esi, eax
1594
 
1595
        push    edx
5565 serge 1596
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SWR
3555 Serge 1597
        pop     edx
5201 serge 1598
        test    eax, eax
1599
        jz      .fail
3555 Serge 1600
 
5984 serge 1601
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_create: %x\n", eax
3555 Serge 1602
 
1603
        pusha
1604
        lea     ecx, [esi + RING_BUFFER.mutex]
1605
        call    mutex_init
1606
        popa
1607
 
1608
        mov     [esi + RING_BUFFER.start_ptr], eax
1609
        mov     [esi + RING_BUFFER.write_ptr], eax
1610
        mov     [esi + RING_BUFFER.read_ptr], eax
1611
        mov     [esi + RING_BUFFER.size], 0
1612
        add     eax, SOCKET_MAXDATA
1613
        mov     [esi + RING_BUFFER.end_ptr], eax
1614
        mov     eax, esi
1615
 
5984 serge 1616
        pop     esi
1617
        ret
1618
 
5201 serge 1619
  .fail:
5984 serge 1620
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ring_create: Out of memory!\n"
5577 serge 1621
        pop     esi
2434 Serge 1622
        ret
261 hidnplayr 1623
 
5984 serge 1624
;-----------------------------------------------------------------;
1625
;                                                                 ;
1626
; SOCKET_ring_write: Write data to ring buffer.                   ;
1627
;                                                                 ;
1628
;   IN: eax = ptr to ring struct                                  ;
1629
;       ecx = data size                                           ;
1630
;       esi = ptr to data                                         ;
1631
;                                                                 ;
1632
;  OUT: ecx = number of bytes stored                              ;
1633
;                                                                 ;
1634
;-----------------------------------------------------------------;
3555 Serge 1635
align 4
1636
SOCKET_ring_write:
261 hidnplayr 1637
 
3589 Serge 1638
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
261 hidnplayr 1639
 
3555 Serge 1640
; lock mutex
1641
        pusha
1642
        lea     ecx, [eax + RING_BUFFER.mutex]
1643
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1644
        popa
261 hidnplayr 1645
 
3555 Serge 1646
; calculate available size
1647
        mov     edi, SOCKET_MAXDATA
1648
        sub     edi, [eax + RING_BUFFER.size]                   ; available buffer size in edi
1649
        cmp     ecx, edi
1650
        jbe     .copy
1651
        mov     ecx, edi
1652
  .copy:
1653
        mov     edi, [eax + RING_BUFFER.write_ptr]
3589 Serge 1654
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3555 Serge 1655
 
1656
; update write ptr
1657
        push    edi
1658
        add     edi, ecx
1659
        cmp     edi, [eax + RING_BUFFER.end_ptr]
1660
        jb      @f
1661
        sub     edi, SOCKET_MAXDATA                             ; WRAP
1662
  @@:
5201 serge 1663
 
3555 Serge 1664
        mov     [eax + RING_BUFFER.write_ptr], edi
1665
        pop     edi
1666
 
1667
; update size
1668
        add     [eax + RING_BUFFER.size], ecx
1669
 
1670
; copy the data
1671
        push    ecx
1672
        shr     ecx, 1
1673
        jnc     .nb
1674
        movsb
1675
  .nb:
1676
        shr     ecx, 1
1677
        jnc     .nw
1678
        movsw
1679
  .nw:
1680
        test    ecx, ecx
1681
        jz      .nd
3725 Serge 1682
        rep movsd
3555 Serge 1683
  .nd:
1684
        pop     ecx
1685
 
1686
; unlock mutex
4423 Serge 1687
        pusha
3555 Serge 1688
        lea     ecx, [eax + RING_BUFFER.mutex]
1689
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
4423 Serge 1690
        popa
3555 Serge 1691
 
2434 Serge 1692
        ret
261 hidnplayr 1693
 
5984 serge 1694
;-----------------------------------------------------------------;
1695
;                                                                 ;
1696
; SOCKET_ring_read: Read from ring buffer                         ;
1697
;                                                                 ;
1698
;   IN: eax = ring struct ptr                                     ;
1699
;       ecx = bytes to read                                       ;
1700
;       edx = offset                                              ;
1701
;       edi = ptr to buffer start                                 ;
1702
;                                                                 ;
1703
;  OUT: eax = unchanged                                           ;
1704
;       ecx = number of bytes read (0 on error)                   ;
1705
;       edx = destroyed                                           ;
1706
;       esi = destroyed                                           ;
1707
;       edi = ptr to buffer end                                   ;
1708
;                                                                 ;
1709
;-----------------------------------------------------------------;
3555 Serge 1710
align 4
1711
SOCKET_ring_read:
922 mikedld 1712
 
3589 Serge 1713
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3555 Serge 1714
 
2434 Serge 1715
        pusha
3555 Serge 1716
        lea     ecx, [eax + RING_BUFFER.mutex]
1717
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1718
        popa
261 hidnplayr 1719
 
3555 Serge 1720
        mov     esi, [eax + RING_BUFFER.read_ptr]
1721
        add     esi, edx                                        ; esi = start_ptr + offset
261 hidnplayr 1722
 
3555 Serge 1723
        neg     edx
1724
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1725
        jle     .no_data_at_all
261 hidnplayr 1726
 
3555 Serge 1727
        pusha
1728
        lea     ecx, [eax + RING_BUFFER.mutex]
1729
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1730
        popa
261 hidnplayr 1731
 
3555 Serge 1732
        cmp     ecx, edx
1733
        ja      .less_data
1734
 
1735
  .copy:
3589 Serge 1736
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3555 Serge 1737
        push    ecx
1738
        shr     ecx, 1
1739
        jnc     .nb
1740
        movsb
1741
  .nb:
1742
        shr     ecx, 1
1743
        jnc     .nw
1744
        movsw
1745
  .nw:
1746
        test    ecx, ecx
1747
        jz      .nd
3725 Serge 1748
        rep movsd
3555 Serge 1749
  .nd:
1750
        pop     ecx
1751
        ret
1752
 
1753
  .no_data_at_all:
1754
        pusha
1755
        lea     ecx, [eax + RING_BUFFER.mutex]
1756
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
2434 Serge 1757
        popa
261 hidnplayr 1758
 
3589 Serge 1759
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3555 Serge 1760
        xor     ecx, ecx
1761
        ret
261 hidnplayr 1762
 
3555 Serge 1763
  .less_data:
1764
        mov     ecx, edx
1765
        jmp     .copy
261 hidnplayr 1766
 
1767
 
5984 serge 1768
;-----------------------------------------------------------------;
1769
;                                                                 ;
1770
; SOCKET_ring_free: Free data from a ringbuffer                   ;
1771
;                                                                 ;
1772
;   IN: eax = ptr to ring struct                                  ;
1773
;       ecx = data size                                           ;
1774
;                                                                 ;
1775
;  OUT: ecx = number of freed bytes                               ;
1776
;                                                                 ;
1777
;-----------------------------------------------------------------;
3555 Serge 1778
align 4
1779
SOCKET_ring_free:
261 hidnplayr 1780
 
3589 Serge 1781
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3555 Serge 1782
 
1783
        push    eax ecx
1784
        lea     ecx, [eax + RING_BUFFER.mutex]
1785
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1786
        pop     ecx eax
1787
 
1788
        sub     [eax + RING_BUFFER.size], ecx
1789
        jb      .error
1790
        add     [eax + RING_BUFFER.read_ptr], ecx
1791
 
1792
        mov     edx, [eax + RING_BUFFER.end_ptr]
1793
        cmp     [eax + RING_BUFFER.read_ptr], edx
1794
        jb      @f
1795
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
1796
       @@:
1797
 
1798
        push    eax ecx
1799
        lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
1800
        call    mutex_unlock
1801
        pop     ecx eax
1802
 
1803
        ret
1804
 
1805
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
3589 Serge 1806
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3555 Serge 1807
        add     [eax + RING_BUFFER.size], ecx
1808
 
2434 Serge 1809
        push    eax
3555 Serge 1810
        lea     ecx, [eax + RING_BUFFER.mutex]
1811
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1812
        pop     eax
261 hidnplayr 1813
 
2434 Serge 1814
        xor     ecx, ecx
3555 Serge 1815
        ret
261 hidnplayr 1816
 
1817
 
5984 serge 1818
;-----------------------------------------------------------------;
1819
;                                                                 ;
1820
; SOCKET_block: Suspend the thread attached to a socket.          ;
1821
;                                                                 ;
1822
;   IN: eax = socket ptr                                          ;
1823
;                                                                 ;
1824
;  OUT: eax = unchanged                                           ;
1825
;                                                                 ;
1826
;-----------------------------------------------------------------;
3555 Serge 1827
align 4
1828
SOCKET_block:
261 hidnplayr 1829
 
3589 Serge 1830
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
261 hidnplayr 1831
 
5201 serge 1832
        push    eax
1833
 
3555 Serge 1834
        pushf
1835
        cli
261 hidnplayr 1836
 
3555 Serge 1837
        ; Set the 'socket is blocked' flag
1838
        or      [eax + SOCKET.state], SS_BLOCKED
261 hidnplayr 1839
 
3555 Serge 1840
        ; Suspend the thread
1841
        push    edx
1842
        mov     edx, [TASK_BASE]
1843
        mov     [edx + TASKDATA.state], 1               ; Suspended
261 hidnplayr 1844
 
3555 Serge 1845
        ; Remember the thread ID so we can wake it up again
1846
        mov     edx, [edx + TASKDATA.pid]
3589 Serge 1847
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3555 Serge 1848
        mov     [eax + SOCKET.TID], edx
1849
        pop     edx
5201 serge 1850
        popf
261 hidnplayr 1851
 
3555 Serge 1852
        call    change_task
3725 Serge 1853
        pop     eax
261 hidnplayr 1854
 
5201 serge 1855
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continuing\n"
261 hidnplayr 1856
 
2434 Serge 1857
        ret
261 hidnplayr 1858
 
3555 Serge 1859
 
5984 serge 1860
;-----------------------------------------------------------------;
1861
;                                                                 ;
1862
; SOCKET_notify: Wake up socket owner thread.                     ;
1863
;                                                                 ;
1864
;   IN: eax = socket ptr                                          ;
1865
;                                                                 ;
1866
;  OUT: eax = unchanged                                           ;
1867
;                                                                 ;
1868
;-----------------------------------------------------------------;
3555 Serge 1869
align 4
1870
SOCKET_notify:
1871
 
3589 Serge 1872
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3555 Serge 1873
 
1874
        call    SOCKET_check
2434 Serge 1875
        jz      .error
261 hidnplayr 1876
 
5201 serge 1877
; Find the associated thread's TASK_DATA
1878
        push    ebx ecx esi
1879
        mov     ebx, [eax + SOCKET.TID]
1880
        test    ebx, ebx
1881
        jz      .error2
1882
        xor     ecx, ecx
3555 Serge 1883
        inc     ecx
5201 serge 1884
        mov     esi, TASK_DATA
1885
  .next:
1886
        cmp     [esi + TASKDATA.pid], ebx
1887
        je      .found
1888
        inc     ecx
3555 Serge 1889
        add     esi, 0x20
1890
        cmp     ecx, [TASK_COUNT]
5201 serge 1891
        jbe     .next
1892
 
1893
  .error2:
3555 Serge 1894
; PID not found, TODO: close socket!
5201 serge 1895
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_notify: error finding thread 0x%x !\n", ebx
1896
        pop     esi ecx ebx
1897
        ret
3555 Serge 1898
 
5201 serge 1899
  .error:
1900
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_notify: invalid socket ptr: 0x%x !\n", eax
1901
        ret
1902
 
1903
  .found:
1904
        test    [eax + SOCKET.state], SS_BLOCKED
1905
        jnz     .un_block
1906
 
5984 serge 1907
; Socket and thread exists and socket is of non blocking type.
5201 serge 1908
; We'll try to flag an event to the thread.
3555 Serge 1909
        shl     ecx, 8
1910
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1911
 
3908 Serge 1912
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: poking thread %u!\n", eax
5201 serge 1913
        pop     esi ecx ebx
1914
        ret
3555 Serge 1915
 
1916
 
5201 serge 1917
  .un_block:
5984 serge 1918
; Socket and thread exists and socket is of blocking type
5201 serge 1919
; We'll try to unblock it.
1920
        and     [eax + SOCKET.state], not SS_BLOCKED    ; Clear the 'socket is blocked' flag
1921
        mov     [esi + TASKDATA.state], 0               ; Run the thread
261 hidnplayr 1922
 
3589 Serge 1923
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
5201 serge 1924
        pop     esi ecx ebx
2434 Serge 1925
        ret
261 hidnplayr 1926
 
3555 Serge 1927
 
5984 serge 1928
;-----------------------------------------------------------------;
1929
;                                                                 ;
1930
; SOCKET_alloc:                                                   ;
1931
; Allocate memory for socket and put new socket into the list.    ;
1932
; Newly created socket is initialized with calling PID and socket ;
1933
; number.                                                         ;
1934
;                                                                 ;
1935
;  IN:  /                                                         ;
1936
;                                                                 ;
1937
; OUT:  eax = socket ptr on success                               ;
1938
;       eax = 0 on error                                          ;
1939
;       edi = socket number on success                            ;
1940
;                                                                 ;
1941
;-----------------------------------------------------------------;
3555 Serge 1942
align 4
1943
SOCKET_alloc:
1944
 
1945
        push    ebx
1946
 
1947
        stdcall kernel_alloc, SOCKETBUFFSIZE
5984 serge 1948
        or      eax, eax
1949
        jz      .nomem
3589 Serge 1950
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
261 hidnplayr 1951
 
3555 Serge 1952
; zero-initialize allocated memory
1953
        push    eax
1954
        mov     edi, eax
1955
        mov     ecx, SOCKETBUFFSIZE / 4
1956
        xor     eax, eax
3725 Serge 1957
        rep stosd
3555 Serge 1958
        pop     eax
1959
 
1960
; set send-and receive procedures to return -1
3725 Serge 1961
        mov     [eax + SOCKET.snd_proc], .not_yet
1962
        mov     [eax + SOCKET.rcv_proc], .not_yet
3555 Serge 1963
 
3725 Serge 1964
        pusha
1965
        mov     ecx, socket_mutex
1966
        call    mutex_lock
1967
        popa
1968
 
3555 Serge 1969
; find first free socket number and use it
1970
        mov     edi, [last_socket_num]
1971
  .next_socket_number:
1972
        inc     edi
1973
        jz      .next_socket_number     ; avoid socket nr 0
1974
        cmp     edi, -1
1975
        je      .next_socket_number     ; avoid socket nr -1
1976
        mov     ebx, net_sockets
1977
  .next_socket:
1978
        mov     ebx, [ebx + SOCKET.NextPtr]
1979
        test    ebx, ebx
1980
        jz      .last_socket
1981
 
1982
        cmp     [ebx + SOCKET.Number], edi
1983
        jne     .next_socket
1984
        jmp     .next_socket_number
1985
 
1986
  .last_socket:
1987
        mov     [last_socket_num], edi
1988
        mov     [eax + SOCKET.Number], edi
3589 Serge 1989
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3555 Serge 1990
 
1991
; Fill in PID
1992
        mov     ebx, [TASK_BASE]
1993
        mov     ebx, [ebx + TASKDATA.pid]
1994
        mov     [eax + SOCKET.PID], ebx
1995
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1996
 
1997
; init mutex
1998
        pusha
2434 Serge 1999
        lea     ecx, [eax + SOCKET.mutex]
3555 Serge 2000
        call    mutex_init
2001
        popa
1019 diamond 2002
 
3555 Serge 2003
; add socket to the list by re-arranging some pointers
2004
        mov     ebx, [net_sockets + SOCKET.NextPtr]
261 hidnplayr 2005
 
3555 Serge 2006
        mov     [eax + SOCKET.PrevPtr], net_sockets
2007
        mov     [eax + SOCKET.NextPtr], ebx
261 hidnplayr 2008
 
3555 Serge 2009
        test    ebx, ebx
2010
        jz      @f
261 hidnplayr 2011
 
3555 Serge 2012
        pusha
2434 Serge 2013
        lea     ecx, [ebx + SOCKET.mutex]
3555 Serge 2014
        call    mutex_lock
2015
        popa
261 hidnplayr 2016
 
3555 Serge 2017
        mov     [ebx + SOCKET.PrevPtr], eax
2018
 
2019
        pusha
2434 Serge 2020
        lea     ecx, [ebx + SOCKET.mutex]
2021
        call    mutex_unlock
3555 Serge 2022
        popa
2023
       @@:
2024
 
2025
        mov     [net_sockets + SOCKET.NextPtr], eax
3725 Serge 2026
 
2027
        pusha
2028
        mov     ecx, socket_mutex
2029
        call    mutex_unlock
2030
        popa
3555 Serge 2031
        pop     ebx
2032
 
2434 Serge 2033
        ret
261 hidnplayr 2034
 
5984 serge 2035
  .nomem:
2036
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_alloc: Out of memory!\n"
2037
        pop     ebx
2038
        ret
2039
 
3725 Serge 2040
  .not_yet:
2041
        mov     dword[esp+20], ENOTCONN
2042
        mov     dword[esp+32], -1
2043
        ret
3555 Serge 2044
 
3725 Serge 2045
 
5984 serge 2046
;-----------------------------------------------------------------;
2047
;                                                                 ;
2048
; SOCKET_free:                                                    ;
2049
; Free socket data memory and remove socket from the list.        ;
2050
; Caller should lock and unlock socket_mutex.                     ;
2051
;                                                                 ;
2052
;  IN:  eax = socket ptr                                          ;
2053
;                                                                 ;
2054
; OUT:  /                                                         ;
2055
;                                                                 ;
2056
;-----------------------------------------------------------------;
3555 Serge 2057
align 4
2058
SOCKET_free:
2059
 
3589 Serge 2060
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3555 Serge 2061
 
2062
        call    SOCKET_check
2434 Serge 2063
        jz      .error
261 hidnplayr 2064
 
3555 Serge 2065
        push    ebx
1019 diamond 2066
 
3555 Serge 2067
        pusha
2434 Serge 2068
        lea     ecx, [eax + SOCKET.mutex]
2069
        call    mutex_lock
3555 Serge 2070
        popa
2130 serge 2071
 
5984 serge 2072
        cmp     [eax + SOCKET.Type], SOCK_STREAM
2073
        jne     .no_stream
323 hidnplayr 2074
 
2434 Serge 2075
        mov     ebx, eax
5984 serge 2076
        cmp     [eax + STREAM_SOCKET.rcv.start_ptr], 0
2077
        je      @f
2078
        stdcall free_kernel_space, [eax + STREAM_SOCKET.rcv.start_ptr]
2079
  @@:
2080
        cmp     [ebx + STREAM_SOCKET.snd.start_ptr], 0
2081
        je      @f
2082
        stdcall free_kernel_space, [ebx + STREAM_SOCKET.snd.start_ptr]
2083
  @@:
2434 Serge 2084
        mov     eax, ebx
5984 serge 2085
  .no_stream:
323 hidnplayr 2086
 
3725 Serge 2087
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3555 Serge 2088
        push    eax                             ; this will be passed to kernel_free
2089
        mov     ebx, [eax + SOCKET.NextPtr]
2090
        mov     eax, [eax + SOCKET.PrevPtr]
2091
 
3589 Serge 2092
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3555 Serge 2093
 
2094
        test    eax, eax
2095
        jz      @f
2096
        mov     [eax + SOCKET.NextPtr], ebx
2097
       @@:
2098
 
2099
        test    ebx, ebx
2100
        jz      @f
2101
        mov     [ebx + SOCKET.PrevPtr], eax
2102
       @@:
2103
 
2104
        call    kernel_free
2105
        pop     ebx
2106
 
3589 Serge 2107
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
3555 Serge 2108
 
907 mikedld 2109
  .error:
2434 Serge 2110
        ret
323 hidnplayr 2111
 
5984 serge 2112
  .error1:
2113
        pop     ebx
2114
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_free: error!\n"
2115
        DEBUGF  DEBUG_NETWORK_ERROR, "socket ptr=0x%x caller=0x%x\n", eax, [esp]
2116
        ret
2117
 
2118
;-----------------------------------------------------------------;
2119
;                                                                 ;
2120
; SOCKET_fork: Create a child socket.                             ;
2121
;                                                                 ;
2122
;  IN:  ebx = socket number                                       ;
2123
;                                                                 ;
2124
; OUT:  eax = child socket number on success                      ;
2125
;       eax = 0 on error                                          ;
2126
;                                                                 ;
2127
;-----------------------------------------------------------------;
3555 Serge 2128
align 4
2129
SOCKET_fork:
2130
 
3589 Serge 2131
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3555 Serge 2132
 
2133
; Exit if backlog queue is full
2134
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
2135
        cmp     ax, [ebx + SOCKET.backlog]
2136
        jae     .fail
2137
 
2138
; Allocate new socket
2139
        push    ebx
2140
        call    SOCKET_alloc
2141
        pop     ebx
5201 serge 2142
        test    eax, eax
3555 Serge 2143
        jz      .fail
2144
 
2145
        push    eax
2146
        mov     esi, esp
2147
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
2148
        pop     eax
2149
 
2150
; Copy structure from current socket to new
3908 Serge 2151
; We start at PID to preserve the socket num, 2 pointers and mutex
2152
; TID will be filled in later
3555 Serge 2153
        lea     esi, [ebx + SOCKET.PID]
2154
        lea     edi, [eax + SOCKET.PID]
2155
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
3725 Serge 2156
        rep movsd
3555 Serge 2157
 
2158
        and     [eax + SOCKET.options], not SO_ACCEPTCON
2159
 
3908 Serge 2160
; Notify owner of parent socket
2161
        push    eax
2162
        mov     eax, ebx
2163
        call    SOCKET_notify
2164
        pop     eax
2165
 
2434 Serge 2166
        ret
323 hidnplayr 2167
 
3555 Serge 2168
  .fail2:
2169
        add     esp, 4+4+4
2170
  .fail:
3589 Serge 2171
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3555 Serge 2172
        xor     eax, eax
2173
        ret
323 hidnplayr 2174
 
3555 Serge 2175
 
5984 serge 2176
;-----------------------------------------------------------------;
2177
;                                                                 ;
2178
; SOCKET_num_to_ptr: Get socket structure address by its number.  ;
2179
;                                                                 ;
2180
;  IN:  ecx = socket number                                       ;
2181
;                                                                 ;
2182
; OUT:  eax = socket ptr                                          ;
2183
;       eax = 0 on error                                          ;
2184
;                                                                 ;
2185
;-----------------------------------------------------------------;
3555 Serge 2186
align 4
2187
SOCKET_num_to_ptr:
2188
 
3589 Serge 2189
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3555 Serge 2190
 
3725 Serge 2191
        pusha
2192
        mov     ecx, socket_mutex
2193
        call    mutex_lock
2194
        popa
2195
 
3555 Serge 2196
        mov     eax, net_sockets
2197
  .next_socket:
2198
        mov     eax, [eax + SOCKET.NextPtr]
5984 serge 2199
        test    eax, eax
2434 Serge 2200
        jz      .error
3555 Serge 2201
        cmp     [eax + SOCKET.Number], ecx
2202
        jne     .next_socket
261 hidnplayr 2203
 
3725 Serge 2204
        pusha
2205
        mov     ecx, socket_mutex
2206
        call    mutex_unlock
2207
        popa
2208
 
3589 Serge 2209
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3555 Serge 2210
        ret
261 hidnplayr 2211
 
3555 Serge 2212
  .error:
3725 Serge 2213
        pusha
2214
        mov     ecx, socket_mutex
2215
        call    mutex_unlock
2216
        popa
2217
 
5201 serge 2218
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: socket %u not found!\n", eax
2219
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: caller = 0x%x\n", [esp]
3555 Serge 2220
        ret
261 hidnplayr 2221
 
2222
 
5984 serge 2223
;-----------------------------------------------------------------;
2224
;                                                                 ;
2225
; SOCKET_ptr_to_num: Get socket number by its address.            ;
2226
;                                                                 ;
2227
;  IN:  eax = socket ptr                                          ;
2228
;                                                                 ;
2229
; OUT:  eax = socket number                                       ;
2230
;       eax = 0 on error                                          ;
2231
;       ZF = set on error                                         ;
2232
;                                                                 ;
2233
;-----------------------------------------------------------------;
3555 Serge 2234
align 4
2235
SOCKET_ptr_to_num:
261 hidnplayr 2236
 
3589 Serge 2237
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
261 hidnplayr 2238
 
3555 Serge 2239
        call    SOCKET_check
2240
        jz      .error
261 hidnplayr 2241
 
3555 Serge 2242
        mov     eax, [eax + SOCKET.Number]
261 hidnplayr 2243
 
3589 Serge 2244
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3555 Serge 2245
        ret
261 hidnplayr 2246
 
3555 Serge 2247
  .error:
3589 Serge 2248
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3555 Serge 2249
        ret
261 hidnplayr 2250
 
2251
 
5984 serge 2252
;-----------------------------------------------------------------;
2253
;                                                                 ;
2254
; SOCKET_check: Checks if the given ptr is really a socket ptr.   ;
2255
;                                                                 ;
2256
;  IN:  eax = socket ptr                                          ;
2257
;                                                                 ;
2258
; OUT:  eax = 0 on error                                          ;
2259
;       ZF = set on error                                         ;
2260
;                                                                 ;
2261
;-----------------------------------------------------------------;
3555 Serge 2262
align 4
2263
SOCKET_check:
261 hidnplayr 2264
 
3589 Serge 2265
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
261 hidnplayr 2266
 
5984 serge 2267
        test    eax, eax
2268
        jz      .error
3555 Serge 2269
        push    ebx
2270
        mov     ebx, net_sockets
261 hidnplayr 2271
 
3555 Serge 2272
  .next_socket:
2273
        mov     ebx, [ebx + SOCKET.NextPtr]
2274
        or      ebx, ebx
2275
        jz      .done
2276
        cmp     ebx, eax
2277
        jnz     .next_socket
261 hidnplayr 2278
 
3555 Serge 2279
  .done:
2280
        mov     eax, ebx
2281
        test    eax, eax
2282
        pop     ebx
5984 serge 2283
        ret
261 hidnplayr 2284
 
5984 serge 2285
  .error:
2286
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_check: called with argument 0\n"
2287
        DEBUGF  DEBUG_NETWORK_ERROR, "stack: 0x%x, 0x%x, 0x%x\n", [esp], [esp+4], [esp+8]
3555 Serge 2288
        ret
261 hidnplayr 2289
 
2290
 
2291
 
5984 serge 2292
;-----------------------------------------------------------------;
2293
;                                                                 ;
2294
; SOCKET_check_owner: Check if the caller app owns the socket.    ;
2295
;                                                                 ;
2296
;  IN:  eax = socket ptr                                          ;
2297
;                                                                 ;
2298
; OUT:  ZF = true/false                                           ;
2299
;                                                                 ;
2300
;-----------------------------------------------------------------;
3555 Serge 2301
align 4
2302
SOCKET_check_owner:
261 hidnplayr 2303
 
3589 Serge 2304
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
261 hidnplayr 2305
 
3555 Serge 2306
        push    ebx
2307
        mov     ebx, [TASK_BASE]
2308
        mov     ebx, [ebx + TASKDATA.pid]
2309
        cmp     [eax + SOCKET.PID], ebx
3725 Serge 2310
        pop     ebx
261 hidnplayr 2311
 
3555 Serge 2312
        ret
261 hidnplayr 2313
 
2314
 
2315
 
2316
 
5984 serge 2317
;-----------------------------------------------------------------;
2318
;                                                                 ;
2319
; SOCKET_process_end:                                             ;
2320
; Kernel calls this function when a certain process ends.         ;
2321
; This function will check if the process had any open sockets,   ;
2322
; and update them accordingly (clean up).                         ;
2323
;                                                                 ;
2324
;  IN:  edx = pid                                                 ;
2325
;                                                                 ;
2326
; OUT:  /                                                         ;
2327
;                                                                 ;
2328
;-----------------------------------------------------------------;
3555 Serge 2329
align 4
2330
SOCKET_process_end:
261 hidnplayr 2331
 
5201 serge 2332
        ret     ; FIXME
2333
 
4265 Serge 2334
        cmp     [net_sockets + SOCKET.NextPtr], 0       ; Are there any active sockets at all?
2335
        je      .quickret                               ; nope, exit immediately
2336
 
2337
; TODO: run the following code in another thread, to avoid deadlock
2338
 
3589 Serge 2339
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
261 hidnplayr 2340
 
3725 Serge 2341
        pusha
2342
        mov     ecx, socket_mutex
2343
        call    mutex_lock
2344
        popa
2345
 
3555 Serge 2346
        push    ebx
2347
        mov     ebx, net_sockets
261 hidnplayr 2348
 
3555 Serge 2349
  .next_socket:
2350
        mov     ebx, [ebx + SOCKET.NextPtr]
2351
  .next_socket_test:
2352
        test    ebx, ebx
2353
        jz      .done
261 hidnplayr 2354
 
3555 Serge 2355
        cmp     [ebx + SOCKET.PID], edx
2356
        jne     .next_socket
261 hidnplayr 2357
 
3589 Serge 2358
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
261 hidnplayr 2359
 
3555 Serge 2360
        mov     [ebx + SOCKET.PID], 0
2361
        mov     eax, ebx
2362
        mov     ebx, [ebx + SOCKET.NextPtr]
3725 Serge 2363
 
3555 Serge 2364
        pusha
3725 Serge 2365
        cmp     [eax + SOCKET.Domain], AF_INET4
2366
        jne     .free
2367
 
2368
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2369
        jne     .free
2370
 
4423 Serge 2371
        call    TCP_disconnect
3725 Serge 2372
        jmp     .closed
2373
 
2374
  .free:
2375
        call    SOCKET_free
2376
 
2377
  .closed:
2378
        popa
3555 Serge 2379
        jmp     .next_socket_test
2380
 
2381
  .done:
2382
        pop     ebx
2383
 
3725 Serge 2384
        pusha
2385
        mov     ecx, socket_mutex
2386
        call    mutex_unlock
2387
        popa
2388
 
4265 Serge 2389
  .quickret:
2434 Serge 2390
        ret
261 hidnplayr 2391
 
3555 Serge 2392
 
2393
 
2394
 
5984 serge 2395
;-----------------------------------------------------------------;
2396
;                                                                 ;
2397
; SOCKET_is_connecting: Update socket state.                      ;
2398
;                                                                 ;
2399
;  IN:  eax = socket ptr                                          ;
2400
;                                                                 ;
2401
;  OUT: /                                                         ;
2402
;                                                                 ;
2403
;-----------------------------------------------------------------;
3555 Serge 2404
align 4
2405
SOCKET_is_connecting:
261 hidnplayr 2406
 
3589 Serge 2407
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
261 hidnplayr 2408
 
4265 Serge 2409
        and     [eax + SOCKET.state], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2410
        or      [eax + SOCKET.state], SS_ISCONNECTING
2411
        ret
261 hidnplayr 2412
 
2413
 
2414
 
5984 serge 2415
;-----------------------------------------------------------------;
2416
;                                                                 ;
2417
; SOCKET_is_connected: Update socket state.                       ;
2418
;                                                                 ;
2419
;  IN:  eax = socket ptr                                          ;
2420
;                                                                 ;
2421
;  OUT: /                                                         ;
2422
;                                                                 ;
2423
;-----------------------------------------------------------------;
3555 Serge 2424
align 4
2425
SOCKET_is_connected:
261 hidnplayr 2426
 
3589 Serge 2427
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
261 hidnplayr 2428
 
3725 Serge 2429
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2430
        or      [eax + SOCKET.state], SS_ISCONNECTED
3555 Serge 2431
        jmp     SOCKET_notify
261 hidnplayr 2432
 
2433
 
2434
 
2435
 
5984 serge 2436
;-----------------------------------------------------------------;
2437
;                                                                 ;
2438
; SOCKET_is_disconnecting: Update socket state.                   ;
2439
;                                                                 ;
2440
;  IN:  eax = socket ptr                                          ;
2441
;                                                                 ;
2442
;  OUT: /                                                         ;
2443
;                                                                 ;
2444
;-----------------------------------------------------------------;
3555 Serge 2445
align 4
2446
SOCKET_is_disconnecting:
261 hidnplayr 2447
 
3589 Serge 2448
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
261 hidnplayr 2449
 
3725 Serge 2450
        and     [eax + SOCKET.state], not (SS_ISCONNECTING)
2451
        or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
3555 Serge 2452
        jmp     SOCKET_notify
261 hidnplayr 2453
 
2454
 
2455
 
5984 serge 2456
;-----------------------------------------------------------------;
2457
;                                                                 ;
2458
; SOCKET_is_disconnected: Update socket state.                    ;
2459
;                                                                 ;
2460
;  IN:  eax = socket ptr                                          ;
2461
;                                                                 ;
2462
;  OUT: /                                                         ;
2463
;                                                                 ;
2464
;-----------------------------------------------------------------;
3555 Serge 2465
align 4
2466
SOCKET_is_disconnected:
261 hidnplayr 2467
 
3589 Serge 2468
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
261 hidnplayr 2469
 
3725 Serge 2470
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2471
        or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
3555 Serge 2472
        jmp     SOCKET_notify
2473
 
2474
 
2475
 
5984 serge 2476
;-----------------------------------------------------------------;
2477
;                                                                 ;
2478
; SOCKET_cant_recv_more: Update socket state.                     ;
2479
;                                                                 ;
2480
;  IN:  eax = socket ptr                                          ;
2481
;                                                                 ;
2482
;  OUT: /                                                         ;
2483
;                                                                 ;
2484
;-----------------------------------------------------------------;
3555 Serge 2485
align 4
2486
SOCKET_cant_recv_more:
2487
 
3589 Serge 2488
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3555 Serge 2489
 
3725 Serge 2490
        or      [eax + SOCKET.state], SS_CANTRCVMORE
5984 serge 2491
        jmp     SOCKET_notify
3555 Serge 2492
 
3589 Serge 2493
 
261 hidnplayr 2494
 
5984 serge 2495
;-----------------------------------------------------------------;
2496
;                                                                 ;
2497
; SOCKET_cant_send_more: Update socket state.                     ;
2498
;                                                                 ;
2499
;  IN:  eax = socket ptr                                          ;
2500
;                                                                 ;
2501
;  OUT: /                                                         ;
2502
;                                                                 ;
2503
;-----------------------------------------------------------------;
3555 Serge 2504
align 4
2505
SOCKET_cant_send_more:
2506
 
3589 Serge 2507
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3555 Serge 2508
 
3725 Serge 2509
        or      [eax + SOCKET.state], SS_CANTSENDMORE
2510
        mov     [eax + SOCKET.snd_proc], .notconn
5984 serge 2511
        jmp     SOCKET_notify
3555 Serge 2512
 
3725 Serge 2513
  .notconn:
2514
        mov     dword[esp+20], ENOTCONN
2515
        mov     dword[esp+32], -1
5565 serge 2516
        ret