Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
5363 yogev_ezra 3
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved.    ;;
3545 hidnplayr 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
4850 mario79 18
$Revision: 5976 $
3545 hidnplayr 19
 
20
struct  SOCKET
21
 
5976 hidnplayr 22
        NextPtr                 dd ?    ; pointer to next socket in list
23
        PrevPtr                 dd ?    ; pointer to previous socket in list
24
        Number                  dd ?    ; socket number
3545 hidnplayr 25
 
26
        mutex                   MUTEX
27
 
5976 hidnplayr 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
3545 hidnplayr 33
        errorcode               dd ?
5976 hidnplayr 34
        device                  dd ?    ; device pointer, paired socket pointer if it's a local socket
3545 hidnplayr 35
 
36
        options                 dd ?
37
        state                   dd ?
5976 hidnplayr 38
        backlog                 dw ?    ; number of incoming connections that can be queued
3545 hidnplayr 39
 
40
        snd_proc                dd ?
41
        rcv_proc                dd ?
4030 hidnplayr 42
        connect_proc            dd ?
3545 hidnplayr 43
 
44
ends
45
 
46
struct  IP_SOCKET               SOCKET
47
 
5976 hidnplayr 48
        LocalIP                 rd 4    ; network byte order
49
        RemoteIP                rd 4    ; network byte order
5842 hidnplayr 50
        ttl                     db ?
5976 hidnplayr 51
                                rb 3    ; align
3545 hidnplayr 52
 
53
ends
54
 
55
struct  TCP_SOCKET              IP_SOCKET
56
 
5976 hidnplayr 57
        LocalPort               dw ?    ; network byte order
58
        RemotePort              dw ?    ; network byte order
3545 hidnplayr 59
 
5976 hidnplayr 60
        t_state                 dd ?    ; TCB state
3545 hidnplayr 61
        t_rxtshift              db ?
5976 hidnplayr 62
                                rb 3    ; align
3545 hidnplayr 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
5976 hidnplayr 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
3545 hidnplayr 80
 
81
; receive sequence
5976 hidnplayr 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
3545 hidnplayr 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
4339 hidnplayr 97
        SND_CWND                dd ?    ; congestion window
98
        SND_SSTHRESH            dd ?    ; slow start threshold
3545 hidnplayr 99
 
100
;----------------------
101
; Transmit timing stuff
102
        t_idle                  dd ?
5442 hidnplayr 103
        t_rtt                   dd ?    ; round trip time
3545 hidnplayr 104
        t_rtseq                 dd ?
5442 hidnplayr 105
        t_srtt                  dd ?    ; smoothed round trip time
3545 hidnplayr 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
3600 hidnplayr 132
        timer_flags             dd ?
5976 hidnplayr 133
        timer_retransmission    dd ?    ; rexmt
3545 hidnplayr 134
        timer_persist           dd ?
5976 hidnplayr 135
        timer_keepalive         dd ?    ; keepalive/syn timeout
136
        timer_timed_wait        dd ?    ; also used as 2msl timer
4021 hidnplayr 137
        timer_connect           dd ?
3545 hidnplayr 138
 
139
; extra
140
 
5976 hidnplayr 141
        ts_ecr                  dd ?    ; timestamp echo reply
3545 hidnplayr 142
        ts_val                  dd ?
143
 
5976 hidnplayr 144
        seg_next                dd ?    ; re-assembly queue
3545 hidnplayr 145
 
146
ends
147
 
148
struct  UDP_SOCKET              IP_SOCKET
149
 
5976 hidnplayr 150
        LocalPort               dw ?    ; in network byte order
151
        RemotePort              dw ?    ; in network byte order
3545 hidnplayr 152
 
153
ends
154
 
155
struct  RING_BUFFER
156
 
157
        mutex                   MUTEX
5976 hidnplayr 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
3545 hidnplayr 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 ?
5522 hidnplayr 176
        data_size               dd ?
3545 hidnplayr 177
        buf_ptr                 dd ?
178
 
179
ends
180
 
5976 hidnplayr 181
struct  socket_options
3545 hidnplayr 182
 
5976 hidnplayr 183
        level                   dd ?
184
        optname                 dd ?
185
        optlen                  dd ?
186
        optval                  dd ?
3545 hidnplayr 187
 
5976 hidnplayr 188
ends
189
 
190
SOCKETBUFFSIZE          = 4096          ; in bytes
191
 
192
SOCKET_QUEUE_SIZE       = 10            ; maximum number of incoming packets queued for 1 socket
3545 hidnplayr 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
 
196
uglobal
3698 hidnplayr 197
align 4
198
 
3545 hidnplayr 199
        net_sockets     rd 4
200
        last_socket_num dd ?
5976 hidnplayr 201
        last_UDP_port   dw ?            ; last used ephemeral port
202
        last_TCP_port   dw ?            ;
3647 hidnplayr 203
        socket_mutex    MUTEX
3698 hidnplayr 204
 
3545 hidnplayr 205
endg
206
 
207
 
5976 hidnplayr 208
;-----------------------------------------------------------------;
209
;                                                                 ;
210
; SOCKET_init                                                     ;
211
;                                                                 ;
212
;-----------------------------------------------------------------;
3545 hidnplayr 213
macro   SOCKET_init {
214
 
215
        xor     eax, eax
216
        mov     edi, net_sockets
217
        mov     ecx, 5
3711 clevermous 218
        rep stosd
3545 hidnplayr 219
 
220
       @@:
221
        pseudo_random eax
3600 hidnplayr 222
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 223
        jb      @r
3600 hidnplayr 224
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 225
        ja      @r
226
        xchg    al, ah
227
        mov     [last_UDP_port], ax
228
 
229
       @@:
230
        pseudo_random eax
3600 hidnplayr 231
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 232
        jb      @r
3600 hidnplayr 233
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 234
        ja      @r
235
        xchg    al, ah
236
        mov     [last_TCP_port], ax
237
 
3647 hidnplayr 238
        mov     ecx, socket_mutex
239
        call    mutex_init
240
 
3545 hidnplayr 241
}
242
 
5976 hidnplayr 243
;-----------------------------------------------------------------;
244
;                                                                 ;
245
; Sockets API (system function 75)                                ;
246
;                                                                 ;
247
;-----------------------------------------------------------------;
3545 hidnplayr 248
align 4
249
sys_socket:
250
 
3673 hidnplayr 251
        mov     dword[esp+20], 0        ; Set error code to 0
3659 hidnplayr 252
 
3545 hidnplayr 253
        cmp     ebx, 255
254
        jz      SOCKET_debug
255
 
256
        cmp     ebx, .number
3658 hidnplayr 257
        ja      .error
3545 hidnplayr 258
        jmp     dword [.table + 4*ebx]
259
 
260
  .table:
5976 hidnplayr 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
3545 hidnplayr 272
  .number = ($ - .table) / 4 - 1
273
 
3658 hidnplayr 274
  .error:
275
        mov     dword[esp+32], -1
3673 hidnplayr 276
        mov     dword[esp+20], EINVAL
3545 hidnplayr 277
 
278
        ret
279
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 293
align 4
294
SOCKET_open:
295
 
3556 hidnplayr 296
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x ", ecx, edx, esi
3545 hidnplayr 297
 
298
        push    ecx edx esi
299
        call    SOCKET_alloc
300
        pop     esi edx ecx
4535 hidnplayr 301
        test    eax, eax
3658 hidnplayr 302
        jz      .nobuffs
3545 hidnplayr 303
 
5976 hidnplayr 304
        mov     [esp+32], edi           ; return socketnumber
3556 hidnplayr 305
        DEBUGF  DEBUG_NETWORK_VERBOSE, "socknum=%u\n", edi
3545 hidnplayr 306
 
3705 hidnplayr 307
        test    edx, SO_NONBLOCK
308
        jz      @f
309
        or      [eax + SOCKET.options], SO_NONBLOCK
310
        and     edx, not SO_NONBLOCK
311
  @@:
3545 hidnplayr 312
 
313
        mov     [eax + SOCKET.Domain], ecx
314
        mov     [eax + SOCKET.Type], edx
315
        mov     [eax + SOCKET.Protocol], esi
4030 hidnplayr 316
        mov     [eax + SOCKET.connect_proc], connect_notsupp
3545 hidnplayr 317
 
318
        cmp     ecx, AF_INET4
319
        jne     .no_inet4
320
 
5842 hidnplayr 321
        mov     [eax + IP_SOCKET.ttl], 128
322
 
3545 hidnplayr 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:
3658 hidnplayr 340
  .unsupported:
341
        push    eax
342
        call    SOCKET_free
343
        pop     eax
3673 hidnplayr 344
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 345
        mov     dword[esp+32], -1
3545 hidnplayr 346
        ret
347
 
3658 hidnplayr 348
  .nobuffs:
3673 hidnplayr 349
        mov     dword[esp+20], ENOBUFS
3658 hidnplayr 350
        mov     dword[esp+32], -1
351
        ret
352
 
3545 hidnplayr 353
  .raw:
5976 hidnplayr 354
        test    esi, esi        ; IP_PROTO_IP
3658 hidnplayr 355
        jz      .raw_ip
3545 hidnplayr 356
 
357
        cmp     esi, IP_PROTO_ICMP
3658 hidnplayr 358
        je      .raw_icmp
3545 hidnplayr 359
 
3658 hidnplayr 360
        jmp     .unsupported
3545 hidnplayr 361
 
362
align 4
363
  .udp:
5842 hidnplayr 364
        push    eax
365
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
366
        pop     eax
367
 
3545 hidnplayr 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
4030 hidnplayr 371
        mov     [eax + SOCKET.connect_proc], UDP_connect
3545 hidnplayr 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
4030 hidnplayr 379
        mov     [eax + SOCKET.connect_proc], TCP_connect
3545 hidnplayr 380
 
381
        TCP_init_socket eax
382
        ret
383
 
384
 
385
align 4
3658 hidnplayr 386
  .raw_ip:
5842 hidnplayr 387
        push    eax
388
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
389
        pop     eax
390
 
3545 hidnplayr 391
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
392
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
4030 hidnplayr 393
        mov     [eax + SOCKET.connect_proc], IPv4_connect
3545 hidnplayr 394
        ret
395
 
396
 
397
align 4
3658 hidnplayr 398
  .raw_icmp:
5842 hidnplayr 399
        push    eax
400
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
401
        pop     eax
402
 
3545 hidnplayr 403
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
404
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
4030 hidnplayr 405
        mov     [eax + SOCKET.connect_proc], IPv4_connect
3545 hidnplayr 406
        ret
407
 
408
align 4
409
  .pppoe:
410
        push    eax
411
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
412
        pop     eax
413
 
414
        mov     [eax + SOCKET.snd_proc], SOCKET_send_pppoe
415
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
416
        ret
417
 
418
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 432
align 4
433
SOCKET_bind:
434
 
3556 hidnplayr 435
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 436
 
437
        call    SOCKET_num_to_ptr
5969 hidnplayr 438
        test    eax, eax
3658 hidnplayr 439
        jz      .invalid
3545 hidnplayr 440
 
441
        cmp     esi, 2
3658 hidnplayr 442
        jb      .invalid
3545 hidnplayr 443
 
5976 hidnplayr 444
        cmp     [eax + UDP_SOCKET.LocalPort], 0 ; Socket can only be bound once
4052 hidnplayr 445
        jnz     .invalid
446
 
3545 hidnplayr 447
        cmp     word [edx], AF_INET4
448
        je      .af_inet4
449
 
450
        cmp     word [edx], AF_LOCAL
451
        je      .af_local
452
 
3658 hidnplayr 453
  .notsupp:
3673 hidnplayr 454
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 455
        mov     dword[esp+32], -1
456
        ret
3545 hidnplayr 457
 
3658 hidnplayr 458
  .invalid:
3673 hidnplayr 459
        mov     dword[esp+20], EINVAL
3658 hidnplayr 460
        mov     dword[esp+32], -1
461
        ret
462
 
3545 hidnplayr 463
  .af_local:
464
        ; TODO: write code here
3658 hidnplayr 465
        mov     dword[esp+32], 0
3545 hidnplayr 466
        ret
467
 
468
  .af_inet4:
469
        cmp     esi, 6
3658 hidnplayr 470
        jb      .invalid
3545 hidnplayr 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
 
3658 hidnplayr 478
        jmp     .notsupp
3545 hidnplayr 479
 
480
  .tcp:
481
  .udp:
482
 
4052 hidnplayr 483
        pushd   [edx + 4]                       ; First, fill in the IP
484
        popd    [eax + IP_SOCKET.LocalIP]
3545 hidnplayr 485
 
4052 hidnplayr 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:
3556 hidnplayr 497
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
3545 hidnplayr 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
 
3658 hidnplayr 501
        mov     dword[esp+32], 0
3545 hidnplayr 502
        ret
503
 
3658 hidnplayr 504
  .addrinuse:
505
        mov     dword[esp+32], -1
3673 hidnplayr 506
        mov     dword[esp+20], EADDRINUSE
3658 hidnplayr 507
        ret
3545 hidnplayr 508
 
509
 
510
 
3658 hidnplayr 511
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 525
align 4
526
SOCKET_connect:
527
 
3556 hidnplayr 528
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 529
 
530
        call    SOCKET_num_to_ptr
5969 hidnplayr 531
        test    eax, eax
3658 hidnplayr 532
        jz      .invalid
3545 hidnplayr 533
 
534
        cmp     esi, 8
3658 hidnplayr 535
        jb      .invalid
3545 hidnplayr 536
 
4025 hidnplayr 537
        cmp     [eax + SOCKET.state], SS_ISCONNECTING
538
        je      .already
539
 
540
        test    [eax + SOCKET.options], SO_ACCEPTCON
541
        jnz     .notsupp
542
 
4030 hidnplayr 543
        call    [eax + SOCKET.connect_proc]
3545 hidnplayr 544
 
4030 hidnplayr 545
        mov     dword[esp+20], ebx
546
        mov     dword[esp+32], eax
547
        ret
548
 
549
 
3658 hidnplayr 550
  .notsupp:
3673 hidnplayr 551
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 552
        mov     dword[esp+32], -1
553
        ret
3545 hidnplayr 554
 
3658 hidnplayr 555
  .invalid:
3673 hidnplayr 556
        mov     dword[esp+20], EINVAL
3658 hidnplayr 557
        mov     dword[esp+32], -1
558
        ret
559
 
4025 hidnplayr 560
  .already:
561
        mov     dword[esp+20], EALREADY
562
        mov     dword[esp+32], -1
563
        ret
564
 
565
 
4030 hidnplayr 566
connect_notsupp:
567
        xor     eax, eax
568
        dec     eax
569
        mov     ebx, EOPNOTSUPP
3545 hidnplayr 570
        ret
571
 
4025 hidnplayr 572
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 585
align 4
586
SOCKET_listen:
587
 
3556 hidnplayr 588
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
3545 hidnplayr 589
 
590
        call    SOCKET_num_to_ptr
5969 hidnplayr 591
        test    eax, eax
3658 hidnplayr 592
        jz      .invalid
3545 hidnplayr 593
 
594
        cmp     [eax + SOCKET.Domain], AF_INET4
3658 hidnplayr 595
        jne     .notsupp
3545 hidnplayr 596
 
597
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3658 hidnplayr 598
        jne     .invalid
3545 hidnplayr 599
 
600
        cmp     [eax + TCP_SOCKET.LocalPort], 0
3658 hidnplayr 601
        je      .already
3545 hidnplayr 602
 
603
        cmp     [eax + IP_SOCKET.LocalIP], 0
604
        jne     @f
3601 hidnplayr 605
        push    [IP_LIST + 4]           ;;; fixme!!!!
3545 hidnplayr 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
 
3658 hidnplayr 623
        mov     dword[esp+32], 0
624
        ret
3545 hidnplayr 625
 
3658 hidnplayr 626
  .notsupp:
3673 hidnplayr 627
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 628
        mov     dword[esp+32], -1
3545 hidnplayr 629
        ret
630
 
3658 hidnplayr 631
  .invalid:
3673 hidnplayr 632
        mov     dword[esp+20], EINVAL
3658 hidnplayr 633
        mov     dword[esp+32], -1
634
        ret
3545 hidnplayr 635
 
3658 hidnplayr 636
  .already:
3673 hidnplayr 637
        mov     dword[esp+20], EALREADY
3658 hidnplayr 638
        mov     dword[esp+32], -1
639
        ret
640
 
641
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 655
align 4
656
SOCKET_accept:
657
 
3556 hidnplayr 658
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 659
 
660
        call    SOCKET_num_to_ptr
5969 hidnplayr 661
        test    eax, eax
3658 hidnplayr 662
        jz      .invalid
3545 hidnplayr 663
 
664
        test    [eax + SOCKET.options], SO_ACCEPTCON
3658 hidnplayr 665
        jz      .invalid
3545 hidnplayr 666
 
667
        cmp     [eax + SOCKET.Domain], AF_INET4
3658 hidnplayr 668
        jne     .notsupp
3545 hidnplayr 669
 
670
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3658 hidnplayr 671
        jne     .invalid
3545 hidnplayr 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
 
5969 hidnplayr 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
3545 hidnplayr 684
        mov     ebx, [TASK_BASE]
685
        mov     ebx, [ebx + TASKDATA.pid]
686
        mov     [eax + SOCKET.TID], ebx
687
 
5969 hidnplayr 688
; Return socket number to caller
689
        mov     eax, [eax + SOCKET.Number]
3545 hidnplayr 690
        mov     [esp+32], eax
691
        ret
692
 
693
  .block:
694
        test    [eax + SOCKET.options], SO_NONBLOCK
3658 hidnplayr 695
        jnz     .wouldblock
3545 hidnplayr 696
 
697
        call    SOCKET_block
698
        jmp     .loop
699
 
3658 hidnplayr 700
  .wouldblock:
3673 hidnplayr 701
        mov     dword[esp+20], EWOULDBLOCK
3658 hidnplayr 702
        mov     dword[esp+32], -1
703
        ret
704
 
705
  .invalid:
3673 hidnplayr 706
        mov     dword[esp+20], EINVAL
3658 hidnplayr 707
        mov     dword[esp+32], -1
708
        ret
709
 
710
  .notsupp:
3673 hidnplayr 711
        mov     dword[esp+20], EOPNOTSUPP
3658 hidnplayr 712
        mov     dword[esp+32], -1
713
        ret
714
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 726
align 4
727
SOCKET_close:
728
 
3556 hidnplayr 729
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
3545 hidnplayr 730
 
731
        call    SOCKET_num_to_ptr
5969 hidnplayr 732
        test    eax, eax
3658 hidnplayr 733
        jz      .invalid
3545 hidnplayr 734
 
3658 hidnplayr 735
        mov     dword[esp+32], 0                                ; The socket exists, so we will succeed in closing it.
3545 hidnplayr 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?
740
        jz      @f
4528 hidnplayr 741
        call    SOCKET_notify                                   ; Unblock it.
3545 hidnplayr 742
  @@:
743
 
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
 
4366 hidnplayr 757
        test    eax, eax
758
        jz      @f
759
        call    TCP_output                                      ; If connection is not closed yet, send the FIN
760
  @@:
3545 hidnplayr 761
        ret
762
 
763
 
3658 hidnplayr 764
  .invalid:
3673 hidnplayr 765
        mov     dword[esp+20], EINVAL
3658 hidnplayr 766
        mov     dword[esp+32], -1
767
        ret
768
 
769
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 785
align 4
786
SOCKET_receive:
787
 
3556 hidnplayr 788
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 789
 
790
        call    SOCKET_num_to_ptr
5969 hidnplayr 791
        test    eax, eax
3658 hidnplayr 792
        jz      .invalid
3545 hidnplayr 793
 
3704 hidnplayr 794
  .loop:
795
        push    edi
3565 hidnplayr 796
        call    [eax + SOCKET.rcv_proc]
3704 hidnplayr 797
        pop     edi
3545 hidnplayr 798
 
4219 hidnplayr 799
        test    [eax + SOCKET.state], SS_CANTRCVMORE
5364 hidnplayr 800
        jnz     .last_data
4219 hidnplayr 801
 
3704 hidnplayr 802
        cmp     ebx, EWOULDBLOCK
803
        jne     .return
804
 
805
        test    edi, MSG_DONTWAIT
806
        jnz     .return_err
807
 
5976 hidnplayr 808
        test    [eax + SOCKET.options], SO_NONBLOCK
809
        jnz     .return_err
3704 hidnplayr 810
 
811
        call    SOCKET_block
812
        jmp     .loop
813
 
814
 
815
  .invalid:
816
        push    EINVAL
817
        pop     ebx
818
  .return_err:
4219 hidnplayr 819
        mov     ecx, -1
3704 hidnplayr 820
  .return:
3673 hidnplayr 821
        mov     [esp+20], ebx
4219 hidnplayr 822
        mov     [esp+32], ecx
3565 hidnplayr 823
        ret
3545 hidnplayr 824
 
5364 hidnplayr 825
  .last_data:
826
        test    ecx, ecx
827
        jz      .return
5976 hidnplayr 828
        call    SOCKET_notify                                   ; Call me again!
5364 hidnplayr 829
        jmp     .return
3565 hidnplayr 830
 
3658 hidnplayr 831
 
3704 hidnplayr 832
 
833
 
3545 hidnplayr 834
align 4
835
SOCKET_receive_dgram:
3704 hidnplayr 836
 
3556 hidnplayr 837
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3545 hidnplayr 838
 
5976 hidnplayr 839
        test    edi, MSG_PEEK
840
        jnz     .peek
3545 hidnplayr 841
 
5976 hidnplayr 842
        mov     ebx, esi                                        ; buffer length
843
 
3704 hidnplayr 844
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success.
3545 hidnplayr 845
        mov     ecx, [esi + socket_queue_entry.data_size]
3556 hidnplayr 846
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3545 hidnplayr 847
 
3704 hidnplayr 848
        cmp     ecx, ebx                                        ; If data segment does not fit in applications buffer, abort
3545 hidnplayr 849
        ja      .too_small
850
 
4219 hidnplayr 851
        push    eax ecx
3545 hidnplayr 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]
3556 hidnplayr 854
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3545 hidnplayr 855
 
3704 hidnplayr 856
; copy the data from kernel buffer to application buffer
857
        mov     edi, edx                                        ; bufferaddr
3545 hidnplayr 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
3711 clevermous 868
        rep movsd
3545 hidnplayr 869
  .nd:
870
 
5522 hidnplayr 871
        call    NET_BUFF_free
4219 hidnplayr 872
        pop     ecx eax                                         ; return number of bytes copied to application
5976 hidnplayr 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)
3545 hidnplayr 878
        ret
879
 
880
  .too_small:
4219 hidnplayr 881
        mov     ecx, -1
3704 hidnplayr 882
        push    EMSGSIZE
883
        pop     ebx
3565 hidnplayr 884
        ret
3545 hidnplayr 885
 
3658 hidnplayr 886
  .wouldblock:
3704 hidnplayr 887
        push    EWOULDBLOCK
888
        pop     ebx
3658 hidnplayr 889
        ret
3545 hidnplayr 890
 
5976 hidnplayr 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
3658 hidnplayr 900
 
3704 hidnplayr 901
 
3545 hidnplayr 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
910
        mov     ebx, [TASK_BASE]
911
        mov     ebx, [ebx + TASKDATA.pid]
912
        mov     [eax + SOCKET.PID], ebx
3704 hidnplayr 913
        mov     [eax + SOCKET.TID], ebx                         ; currently TID = PID in kolibrios :(
3545 hidnplayr 914
      @@:
915
 
916
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_stream
917
 
3704 hidnplayr 918
; ... continue to SOCKET_receive_stream
919
 
3545 hidnplayr 920
align 4
921
SOCKET_receive_stream:
922
 
3556 hidnplayr 923
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3545 hidnplayr 924
 
3704 hidnplayr 925
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
926
        je      .wouldblock
927
 
928
        test    edi, MSG_PEEK
929
        jnz     .peek
930
 
3545 hidnplayr 931
        mov     ecx, esi
932
        mov     edi, edx
933
        xor     edx, edx
934
 
4219 hidnplayr 935
        push    eax
3545 hidnplayr 936
        add     eax, STREAM_SOCKET.rcv
3704 hidnplayr 937
        call    SOCKET_ring_read                                ; copy data from kernel buffer to application buffer
938
        call    SOCKET_ring_free                                ; free read memory
4219 hidnplayr 939
        pop     eax
3545 hidnplayr 940
 
5364 hidnplayr 941
        cmp     [eax + STREAM_SOCKET.rcv + RING_BUFFER.size], 0
942
        jne     .more_data
3704 hidnplayr 943
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
3545 hidnplayr 944
        ret
945
 
5364 hidnplayr 946
  .more_data:
947
        call    SOCKET_notify                                   ; Queue another network event
948
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
949
        ret
950
 
3704 hidnplayr 951
  .wouldblock:
952
        push    EWOULDBLOCK
953
        pop     ebx
4219 hidnplayr 954
        xor     ecx, ecx
3704 hidnplayr 955
        ret
956
 
3545 hidnplayr 957
  .peek:
4219 hidnplayr 958
        mov     ecx, [eax + STREAM_SOCKET.rcv + RING_BUFFER.size]
3704 hidnplayr 959
        xor     ebx, ebx
3545 hidnplayr 960
        ret
961
 
962
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 977
align 4
978
SOCKET_send:
979
 
3556 hidnplayr 980
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 981
 
982
        call    SOCKET_num_to_ptr
5969 hidnplayr 983
        test    eax, eax
3658 hidnplayr 984
        jz      .invalid
3545 hidnplayr 985
 
986
        mov     ecx, esi
987
        mov     esi, edx
988
 
989
        jmp     [eax + SOCKET.snd_proc]
990
 
3658 hidnplayr 991
  .invalid:
3673 hidnplayr 992
        mov     dword[esp+20], EINVAL
3658 hidnplayr 993
        mov     dword[esp+32], -1
994
        ret
3545 hidnplayr 995
 
3658 hidnplayr 996
 
3545 hidnplayr 997
align 4
998
SOCKET_send_udp:
999
 
3556 hidnplayr 1000
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3545 hidnplayr 1001
 
1002
        mov     [esp+32], ecx
1003
        call    UDP_output
1004
        cmp     eax, -1
3658 hidnplayr 1005
        je      .error
3545 hidnplayr 1006
        ret
1007
 
3658 hidnplayr 1008
  .error:
1009
        mov     dword[esp+32], -1
3673 hidnplayr 1010
        mov     dword[esp+20], EMSGSIZE ; FIXME: UDP_output should return error codes!
3658 hidnplayr 1011
        ret
3545 hidnplayr 1012
 
3658 hidnplayr 1013
 
3545 hidnplayr 1014
align 4
1015
SOCKET_send_tcp:
1016
 
3556 hidnplayr 1017
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3545 hidnplayr 1018
 
1019
        push    eax
1020
        add     eax, STREAM_SOCKET.snd
1021
        call    SOCKET_ring_write
1022
        pop     eax
1023
 
1024
        mov     [esp+32], ecx
3658 hidnplayr 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]
3673 hidnplayr 1030
        mov     [esp+20], eax
3545 hidnplayr 1031
        ret
1032
 
1033
 
1034
align 4
1035
SOCKET_send_ip:
1036
 
3556 hidnplayr 1037
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3545 hidnplayr 1038
 
1039
        mov     [esp+32], ecx
5842 hidnplayr 1040
        call    IPv4_output_raw
3545 hidnplayr 1041
        cmp     eax, -1
3658 hidnplayr 1042
        je      .error
3545 hidnplayr 1043
        ret
1044
 
3658 hidnplayr 1045
  .error:
5842 hidnplayr 1046
        mov     dword[esp+32], eax
1047
        mov     dword[esp+20], ebx
3658 hidnplayr 1048
        ret
3545 hidnplayr 1049
 
3658 hidnplayr 1050
 
3545 hidnplayr 1051
align 4
1052
SOCKET_send_icmp:
1053
 
3556 hidnplayr 1054
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3545 hidnplayr 1055
 
1056
        mov     [esp+32], ecx
5842 hidnplayr 1057
        call    ICMP_output_raw
3545 hidnplayr 1058
        cmp     eax, -1
3658 hidnplayr 1059
        je      .error
3545 hidnplayr 1060
        ret
1061
 
3658 hidnplayr 1062
  .error:
5842 hidnplayr 1063
        mov     dword[esp+32], eax
1064
        mov     dword[esp+20], ebx
3658 hidnplayr 1065
        ret
3545 hidnplayr 1066
 
3658 hidnplayr 1067
 
3545 hidnplayr 1068
align 4
1069
SOCKET_send_pppoe:
1070
 
3556 hidnplayr 1071
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
3545 hidnplayr 1072
 
1073
        mov     [esp+32], ecx
1074
        mov     ebx, [eax + SOCKET.device]
1075
 
3658 hidnplayr 1076
        call    PPPoE_discovery_output  ; FIXME: errorcodes
3545 hidnplayr 1077
        cmp     eax, -1
3658 hidnplayr 1078
        je      .error
3545 hidnplayr 1079
        ret
1080
 
3658 hidnplayr 1081
  .error:
1082
        mov     dword[esp+32], -1
3673 hidnplayr 1083
        mov     dword[esp+20], EMSGSIZE
3658 hidnplayr 1084
        ret
3545 hidnplayr 1085
 
1086
 
3658 hidnplayr 1087
 
3545 hidnplayr 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
 
3556 hidnplayr 1106
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3545 hidnplayr 1107
 
1108
        ; get the other side's socket and check if it still exists
1109
        mov     eax, [eax + SOCKET.device]
1110
        call    SOCKET_check
3658 hidnplayr 1111
        jz      .invalid
3545 hidnplayr 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
 
3658 hidnplayr 1127
  .invalid:
1128
        mov     dword[esp+32], -1
3673 hidnplayr 1129
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1130
        ret
3545 hidnplayr 1131
 
3658 hidnplayr 1132
 
5976 hidnplayr 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:
3545 hidnplayr 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_*.
1152
 
3556 hidnplayr 1153
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
3545 hidnplayr 1154
 
1155
        call    SOCKET_num_to_ptr
5969 hidnplayr 1156
        test    eax, eax
3658 hidnplayr 1157
        jz      .invalid
3545 hidnplayr 1158
 
1159
        cmp     dword [edx], IP_PROTO_TCP
3658 hidnplayr 1160
        jne     .invalid
3545 hidnplayr 1161
        cmp     dword [edx+4], -2
1162
        je      @f
1163
        cmp     dword [edx+4], -3
3658 hidnplayr 1164
        jne     .invalid
3545 hidnplayr 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
1187
        ret
1188
 
3658 hidnplayr 1189
  .invalid:
1190
        mov     dword[esp+32], -1
3673 hidnplayr 1191
        mov     dword[esp+20], EINVAL
3658 hidnplayr 1192
        ret
3545 hidnplayr 1193
 
1194
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1207
align 4
1208
SOCKET_set_opt:
1209
 
3556 hidnplayr 1210
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3545 hidnplayr 1211
 
1212
        call    SOCKET_num_to_ptr
5969 hidnplayr 1213
        test    eax, eax
3658 hidnplayr 1214
        jz      .invalid
3545 hidnplayr 1215
 
5842 hidnplayr 1216
        cmp     [edx + socket_options.level], IP_PROTO_IP
1217
        je      .ip
1218
        cmp     [edx + socket_options.level], SOL_SOCKET
3658 hidnplayr 1219
        jne     .invalid
3545 hidnplayr 1220
 
5842 hidnplayr 1221
  .socket:
1222
        cmp     [edx + socket_options.optname], SO_BINDTODEVICE
1223
        jne     .invalid
3545 hidnplayr 1224
 
1225
  .bind:
5842 hidnplayr 1226
        cmp     [edx + socket_options.optlen], 0
3545 hidnplayr 1227
        je      .unbind
1228
 
5842 hidnplayr 1229
        movzx   edx, byte[edx + socket_options.optval]
3600 hidnplayr 1230
        cmp     edx, NET_DEVICES_MAX
3658 hidnplayr 1231
        ja      .invalid
3545 hidnplayr 1232
 
1233
        mov     edx, [NET_DRV_LIST + 4*edx]
1234
        test    edx, edx
3658 hidnplayr 1235
        jz      .already
3545 hidnplayr 1236
        mov     [eax + SOCKET.device], edx
1237
 
5584 hidnplayr 1238
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n", eax, edx
3545 hidnplayr 1239
 
3658 hidnplayr 1240
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1241
        ret
1242
 
1243
  .unbind:
1244
        mov     [eax + SOCKET.device], 0
1245
 
3658 hidnplayr 1246
        mov     dword[esp+32], 0        ; success!
3545 hidnplayr 1247
        ret
1248
 
5842 hidnplayr 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
 
3658 hidnplayr 1260
  .already:
3673 hidnplayr 1261
        mov     dword[esp+20], EALREADY
3658 hidnplayr 1262
        mov     dword[esp+32], -1
1263
        ret
3545 hidnplayr 1264
 
5842 hidnplayr 1265
  .invalid:
1266
        mov     dword[esp+20], EINVAL
1267
        mov     dword[esp+32], -1
1268
        ret
3545 hidnplayr 1269
 
3658 hidnplayr 1270
 
1271
 
5842 hidnplayr 1272
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1285
align 4
1286
SOCKET_pair:
1287
 
3556 hidnplayr 1288
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3545 hidnplayr 1289
 
1290
        call    SOCKET_alloc
4535 hidnplayr 1291
        test    eax, eax
3658 hidnplayr 1292
        jz      .nomem1
3545 hidnplayr 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
4535 hidnplayr 1304
        test    eax, eax
3658 hidnplayr 1305
        jz      .nomem2
3673 hidnplayr 1306
        mov     [esp+20], edi   ; application's ebx
3545 hidnplayr 1307
 
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
5155 hidnplayr 1321
        test    eax, eax
5969 hidnplayr 1322
        jz      .nomem2
3545 hidnplayr 1323
 
1324
        lea     eax, [ebx + STREAM_SOCKET.rcv]
1325
        call    SOCKET_ring_create
5155 hidnplayr 1326
        test    eax, eax
1327
        jz      .nomem2
3545 hidnplayr 1328
 
1329
        ret
1330
 
3658 hidnplayr 1331
  .nomem2:
5969 hidnplayr 1332
        mov     eax, [esp+20]
3545 hidnplayr 1333
        call    SOCKET_free
5969 hidnplayr 1334
 
3658 hidnplayr 1335
  .nomem1:
5969 hidnplayr 1336
        mov     eax, [esp+32]
1337
        call    SOCKET_free
1338
 
3658 hidnplayr 1339
        mov     dword[esp+32], -1
5969 hidnplayr 1340
        mov     dword[esp+20], ENOMEM
3658 hidnplayr 1341
        ret
3545 hidnplayr 1342
 
1343
 
1344
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1357
align 4
1358
SOCKET_debug:
1359
 
3556 hidnplayr 1360
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3545 hidnplayr 1361
 
1362
        mov     edi, edx
1363
 
1364
        test    ecx, ecx
1365
        jz      .returnall
1366
 
1367
        call    SOCKET_num_to_ptr
5969 hidnplayr 1368
        test    eax, eax
3658 hidnplayr 1369
        jz      .invalid
3545 hidnplayr 1370
 
1371
        mov     esi, eax
1372
        mov     ecx, SOCKETBUFFSIZE/4
3711 clevermous 1373
        rep movsd
3545 hidnplayr 1374
 
3658 hidnplayr 1375
        mov     dword[esp+32], 0
3545 hidnplayr 1376
        ret
1377
 
1378
  .returnall:
1379
        mov     ebx, net_sockets
1380
  .next_socket:
1381
        mov     ebx, [ebx + SOCKET.NextPtr]
1382
        test    ebx, ebx
1383
        jz      .done
1384
        mov     eax, [ebx + SOCKET.Number]
1385
        stosd
1386
        jmp     .next_socket
1387
  .done:
1388
        xor     eax, eax
1389
        stosd
3658 hidnplayr 1390
        mov     dword[esp+32], eax
1391
        ret
3545 hidnplayr 1392
 
3658 hidnplayr 1393
  .invalid:
1394
        mov     dword[esp+32], -1
5969 hidnplayr 1395
        mov     dword[esp+20], EINVAL
3545 hidnplayr 1396
        ret
1397
 
1398
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1420
align 4
1421
SOCKET_find_port:
1422
 
3556 hidnplayr 1423
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
3545 hidnplayr 1424
 
1425
        push    ebx esi ecx
1426
 
1427
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1428
        je      .udp
1429
 
1430
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1431
        je      .tcp
1432
 
1433
        pop     ecx esi ebx
1434
        ret
1435
 
1436
  .udp:
1437
        mov     bx, [last_UDP_port]
1438
        call    .findit
1439
        mov     [last_UDP_port], bx
1440
 
1441
        pop     ecx esi ebx
1442
        ret
1443
 
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
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1482
align 4
1483
SOCKET_check_port:
1484
 
3556 hidnplayr 1485
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
3545 hidnplayr 1486
 
3647 hidnplayr 1487
        pusha
1488
        mov     ecx, socket_mutex
1489
        call    mutex_lock
1490
        popa
1491
 
3545 hidnplayr 1492
        mov     ecx, [eax + SOCKET.Protocol]
1493
        mov     edx, [eax + IP_SOCKET.LocalIP]
1494
        mov     esi, net_sockets
1495
 
1496
  .next_socket:
1497
        mov     esi, [esi + SOCKET.NextPtr]
1498
        or      esi, esi
1499
        jz      .port_ok
1500
 
1501
        cmp     [esi + SOCKET.Protocol], ecx
1502
        jne     .next_socket
1503
 
1504
        cmp     [esi + IP_SOCKET.LocalIP], edx
1505
        jne     .next_socket
1506
 
1507
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1508
        jne     .next_socket
1509
 
3647 hidnplayr 1510
        pusha
1511
        mov     ecx, socket_mutex
1512
        call    mutex_unlock
1513
        popa
1514
 
3556 hidnplayr 1515
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1516
        ret
1517
 
1518
  .port_ok:
3647 hidnplayr 1519
        pusha
1520
        mov     ecx, socket_mutex
1521
        call    mutex_unlock
1522
        popa
1523
 
3556 hidnplayr 1524
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1525
        mov     [eax + UDP_SOCKET.LocalPort], bx
1526
        or      bx, bx                                  ; clear the zero-flag
1527
        ret
1528
 
1529
 
1530
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1545
align 4
1546
SOCKET_input:
1547
 
3556 hidnplayr 1548
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1549
 
5522 hidnplayr 1550
        push    ecx
3545 hidnplayr 1551
        push    esi
1552
        mov     esi, esp
1553
 
1554
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
1555
 
3556 hidnplayr 1556
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3545 hidnplayr 1557
        add     esp, sizeof.socket_queue_entry
1558
 
1559
        pusha
1560
        lea     ecx, [eax + SOCKET.mutex]
1561
        call    mutex_unlock
1562
        popa
1563
 
1564
        jmp     SOCKET_notify
1565
 
1566
  .full:
3556 hidnplayr 1567
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket %x is full!\n", eax
3545 hidnplayr 1568
 
1569
        pusha
1570
        lea     ecx, [eax + SOCKET.mutex]
1571
        call    mutex_unlock
1572
        popa
1573
 
5842 hidnplayr 1574
        add     esp, 8
5522 hidnplayr 1575
        call    NET_BUFF_free
3545 hidnplayr 1576
        ret
1577
 
1578
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1589
align 4
1590
SOCKET_ring_create:
1591
 
1592
        push    esi
1593
        mov     esi, eax
1594
 
1595
        push    edx
5356 serge 1596
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SWR
3545 hidnplayr 1597
        pop     edx
5155 hidnplayr 1598
        test    eax, eax
1599
        jz      .fail
3545 hidnplayr 1600
 
5969 hidnplayr 1601
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_create: %x\n", eax
3545 hidnplayr 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
 
5969 hidnplayr 1616
        pop     esi
1617
        ret
1618
 
5155 hidnplayr 1619
  .fail:
5969 hidnplayr 1620
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ring_create: Out of memory!\n"
5566 hidnplayr 1621
        pop     esi
3545 hidnplayr 1622
        ret
1623
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1635
align 4
1636
SOCKET_ring_write:
1637
 
3556 hidnplayr 1638
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1639
 
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
1645
 
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]
3556 hidnplayr 1654
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 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
  @@:
5155 hidnplayr 1663
 
3545 hidnplayr 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
3711 clevermous 1682
        rep movsd
3545 hidnplayr 1683
  .nd:
1684
        pop     ecx
1685
 
1686
; unlock mutex
4344 hidnplayr 1687
        pusha
3545 hidnplayr 1688
        lea     ecx, [eax + RING_BUFFER.mutex]
1689
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
4344 hidnplayr 1690
        popa
3545 hidnplayr 1691
 
1692
        ret
1693
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1710
align 4
1711
SOCKET_ring_read:
1712
 
3556 hidnplayr 1713
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3545 hidnplayr 1714
 
1715
        pusha
1716
        lea     ecx, [eax + RING_BUFFER.mutex]
1717
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1718
        popa
1719
 
1720
        mov     esi, [eax + RING_BUFFER.read_ptr]
1721
        add     esi, edx                                        ; esi = start_ptr + offset
1722
 
1723
        neg     edx
1724
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1725
        jle     .no_data_at_all
1726
 
1727
        pusha
1728
        lea     ecx, [eax + RING_BUFFER.mutex]
1729
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1730
        popa
1731
 
1732
        cmp     ecx, edx
1733
        ja      .less_data
1734
 
1735
  .copy:
3556 hidnplayr 1736
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 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
3711 clevermous 1748
        rep movsd
3545 hidnplayr 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
1757
        popa
1758
 
3556 hidnplayr 1759
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: no data at all!\n"
3545 hidnplayr 1760
        xor     ecx, ecx
1761
        ret
1762
 
1763
  .less_data:
1764
        mov     ecx, edx
1765
        jmp     .copy
1766
 
1767
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1778
align 4
1779
SOCKET_ring_free:
1780
 
3556 hidnplayr 1781
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3545 hidnplayr 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..
3556 hidnplayr 1806
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: buffer=%x error!\n", eax
3545 hidnplayr 1807
        add     [eax + RING_BUFFER.size], ecx
1808
 
1809
        push    eax
1810
        lea     ecx, [eax + RING_BUFFER.mutex]
1811
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1812
        pop     eax
1813
 
1814
        xor     ecx, ecx
1815
        ret
1816
 
1817
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1827
align 4
1828
SOCKET_block:
1829
 
3556 hidnplayr 1830
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
3545 hidnplayr 1831
 
4520 hidnplayr 1832
        push    eax
1833
 
3545 hidnplayr 1834
        pushf
1835
        cli
1836
 
1837
        ; Set the 'socket is blocked' flag
1838
        or      [eax + SOCKET.state], SS_BLOCKED
1839
 
1840
        ; Suspend the thread
1841
        push    edx
1842
        mov     edx, [TASK_BASE]
1843
        mov     [edx + TASKDATA.state], 1               ; Suspended
1844
 
1845
        ; Remember the thread ID so we can wake it up again
1846
        mov     edx, [edx + TASKDATA.pid]
3556 hidnplayr 1847
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3545 hidnplayr 1848
        mov     [eax + SOCKET.TID], edx
1849
        pop     edx
4520 hidnplayr 1850
        popf
3545 hidnplayr 1851
 
1852
        call    change_task
3674 hidnplayr 1853
        pop     eax
3545 hidnplayr 1854
 
4520 hidnplayr 1855
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continuing\n"
3545 hidnplayr 1856
 
1857
        ret
1858
 
1859
 
5976 hidnplayr 1860
;-----------------------------------------------------------------;
1861
;                                                                 ;
1862
; SOCKET_notify: Wake up socket owner thread.                     ;
1863
;                                                                 ;
1864
;   IN: eax = socket ptr                                          ;
1865
;                                                                 ;
1866
;  OUT: eax = unchanged                                           ;
1867
;                                                                 ;
1868
;-----------------------------------------------------------------;
3545 hidnplayr 1869
align 4
1870
SOCKET_notify:
1871
 
3556 hidnplayr 1872
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3545 hidnplayr 1873
 
1874
        call    SOCKET_check
1875
        jz      .error
1876
 
4527 hidnplayr 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
3545 hidnplayr 1883
        inc     ecx
4527 hidnplayr 1884
        mov     esi, TASK_DATA
1885
  .next:
1886
        cmp     [esi + TASKDATA.pid], ebx
1887
        je      .found
1888
        inc     ecx
3545 hidnplayr 1889
        add     esi, 0x20
1890
        cmp     ecx, [TASK_COUNT]
4527 hidnplayr 1891
        jbe     .next
1892
 
1893
  .error2:
3545 hidnplayr 1894
; PID not found, TODO: close socket!
4527 hidnplayr 1895
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_notify: error finding thread 0x%x !\n", ebx
1896
        pop     esi ecx ebx
1897
        ret
3545 hidnplayr 1898
 
4527 hidnplayr 1899
  .error:
4528 hidnplayr 1900
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_notify: invalid socket ptr: 0x%x !\n", eax
4527 hidnplayr 1901
        ret
1902
 
1903
  .found:
1904
        test    [eax + SOCKET.state], SS_BLOCKED
4528 hidnplayr 1905
        jnz     .un_block
4527 hidnplayr 1906
 
5976 hidnplayr 1907
; Socket and thread exists and socket is of non blocking type.
4527 hidnplayr 1908
; We'll try to flag an event to the thread.
3545 hidnplayr 1909
        shl     ecx, 8
1910
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1911
 
3817 hidnplayr 1912
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: poking thread %u!\n", eax
4527 hidnplayr 1913
        pop     esi ecx ebx
1914
        ret
3545 hidnplayr 1915
 
4527 hidnplayr 1916
 
4528 hidnplayr 1917
  .un_block:
5976 hidnplayr 1918
; Socket and thread exists and socket is of blocking type
4527 hidnplayr 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
3545 hidnplayr 1922
 
3556 hidnplayr 1923
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
4527 hidnplayr 1924
        pop     esi ecx ebx
3545 hidnplayr 1925
        ret
1926
 
1927
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 1942
align 4
1943
SOCKET_alloc:
1944
 
1945
        push    ebx
1946
 
1947
        stdcall kernel_alloc, SOCKETBUFFSIZE
5969 hidnplayr 1948
        or      eax, eax
1949
        jz      .nomem
3556 hidnplayr 1950
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
3545 hidnplayr 1951
 
1952
; zero-initialize allocated memory
1953
        push    eax
1954
        mov     edi, eax
1955
        mov     ecx, SOCKETBUFFSIZE / 4
1956
        xor     eax, eax
3711 clevermous 1957
        rep stosd
3545 hidnplayr 1958
        pop     eax
1959
 
1960
; set send-and receive procedures to return -1
3658 hidnplayr 1961
        mov     [eax + SOCKET.snd_proc], .not_yet
1962
        mov     [eax + SOCKET.rcv_proc], .not_yet
3545 hidnplayr 1963
 
3647 hidnplayr 1964
        pusha
1965
        mov     ecx, socket_mutex
1966
        call    mutex_lock
1967
        popa
1968
 
3545 hidnplayr 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
3556 hidnplayr 1989
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3545 hidnplayr 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
1999
        lea     ecx, [eax + SOCKET.mutex]
2000
        call    mutex_init
2001
        popa
2002
 
2003
; add socket to the list by re-arranging some pointers
2004
        mov     ebx, [net_sockets + SOCKET.NextPtr]
2005
 
2006
        mov     [eax + SOCKET.PrevPtr], net_sockets
2007
        mov     [eax + SOCKET.NextPtr], ebx
2008
 
2009
        test    ebx, ebx
2010
        jz      @f
2011
 
2012
        pusha
2013
        lea     ecx, [ebx + SOCKET.mutex]
2014
        call    mutex_lock
2015
        popa
2016
 
2017
        mov     [ebx + SOCKET.PrevPtr], eax
2018
 
2019
        pusha
2020
        lea     ecx, [ebx + SOCKET.mutex]
2021
        call    mutex_unlock
2022
        popa
2023
       @@:
2024
 
2025
        mov     [net_sockets + SOCKET.NextPtr], eax
3647 hidnplayr 2026
 
2027
        pusha
2028
        mov     ecx, socket_mutex
2029
        call    mutex_unlock
2030
        popa
3545 hidnplayr 2031
        pop     ebx
2032
 
2033
        ret
2034
 
5969 hidnplayr 2035
  .nomem:
2036
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_alloc: Out of memory!\n"
2037
        pop     ebx
2038
        ret
2039
 
3658 hidnplayr 2040
  .not_yet:
3673 hidnplayr 2041
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2042
        mov     dword[esp+32], -1
2043
        ret
3545 hidnplayr 2044
 
3658 hidnplayr 2045
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 2057
align 4
2058
SOCKET_free:
2059
 
3556 hidnplayr 2060
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3545 hidnplayr 2061
 
2062
        call    SOCKET_check
2063
        jz      .error
2064
 
2065
        push    ebx
2066
 
2067
        pusha
2068
        lea     ecx, [eax + SOCKET.mutex]
2069
        call    mutex_lock
2070
        popa
2071
 
5969 hidnplayr 2072
        cmp     [eax + SOCKET.Type], SOCK_STREAM
2073
        jne     .no_stream
3545 hidnplayr 2074
 
2075
        mov     ebx, eax
5969 hidnplayr 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
  @@:
3545 hidnplayr 2084
        mov     eax, ebx
5969 hidnplayr 2085
  .no_stream:
3545 hidnplayr 2086
 
3652 hidnplayr 2087
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3545 hidnplayr 2088
        push    eax                             ; this will be passed to kernel_free
2089
        mov     ebx, [eax + SOCKET.NextPtr]
2090
        mov     eax, [eax + SOCKET.PrevPtr]
2091
 
3556 hidnplayr 2092
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3545 hidnplayr 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
 
3652 hidnplayr 2107
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
2108
 
2109
  .error:
3545 hidnplayr 2110
        ret
2111
 
5969 hidnplayr 2112
  .error1:
2113
        pop     ebx
5976 hidnplayr 2114
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_free: error!\n"
5969 hidnplayr 2115
        DEBUGF  DEBUG_NETWORK_ERROR, "socket ptr=0x%x caller=0x%x\n", eax, [esp]
2116
        ret
2117
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 2128
align 4
2129
SOCKET_fork:
2130
 
3556 hidnplayr 2131
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3545 hidnplayr 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
4535 hidnplayr 2142
        test    eax, eax
3545 hidnplayr 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
3817 hidnplayr 2151
; We start at PID to preserve the socket num, 2 pointers and mutex
2152
; TID will be filled in later
3545 hidnplayr 2153
        lea     esi, [ebx + SOCKET.PID]
2154
        lea     edi, [eax + SOCKET.PID]
2155
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
3711 clevermous 2156
        rep movsd
3545 hidnplayr 2157
 
2158
        and     [eax + SOCKET.options], not SO_ACCEPTCON
2159
 
3817 hidnplayr 2160
; Notify owner of parent socket
2161
        push    eax
2162
        mov     eax, ebx
2163
        call    SOCKET_notify
2164
        pop     eax
2165
 
3545 hidnplayr 2166
        ret
2167
 
2168
  .fail2:
2169
        add     esp, 4+4+4
2170
  .fail:
3556 hidnplayr 2171
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3545 hidnplayr 2172
        xor     eax, eax
2173
        ret
2174
 
2175
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 2186
align 4
2187
SOCKET_num_to_ptr:
2188
 
3556 hidnplayr 2189
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3545 hidnplayr 2190
 
3647 hidnplayr 2191
        pusha
2192
        mov     ecx, socket_mutex
2193
        call    mutex_lock
2194
        popa
2195
 
3545 hidnplayr 2196
        mov     eax, net_sockets
2197
  .next_socket:
2198
        mov     eax, [eax + SOCKET.NextPtr]
5969 hidnplayr 2199
        test    eax, eax
3545 hidnplayr 2200
        jz      .error
2201
        cmp     [eax + SOCKET.Number], ecx
2202
        jne     .next_socket
2203
 
3647 hidnplayr 2204
        pusha
2205
        mov     ecx, socket_mutex
2206
        call    mutex_unlock
2207
        popa
2208
 
3556 hidnplayr 2209
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3545 hidnplayr 2210
        ret
2211
 
2212
  .error:
3647 hidnplayr 2213
        pusha
2214
        mov     ecx, socket_mutex
2215
        call    mutex_unlock
2216
        popa
2217
 
4574 hidnplayr 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]
3545 hidnplayr 2220
        ret
2221
 
2222
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 2234
align 4
2235
SOCKET_ptr_to_num:
2236
 
3556 hidnplayr 2237
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
3545 hidnplayr 2238
 
2239
        call    SOCKET_check
2240
        jz      .error
2241
 
2242
        mov     eax, [eax + SOCKET.Number]
2243
 
3556 hidnplayr 2244
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3545 hidnplayr 2245
        ret
2246
 
2247
  .error:
3556 hidnplayr 2248
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3545 hidnplayr 2249
        ret
2250
 
2251
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 2262
align 4
2263
SOCKET_check:
2264
 
3556 hidnplayr 2265
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
3545 hidnplayr 2266
 
5969 hidnplayr 2267
        test    eax, eax
2268
        jz      .error
3545 hidnplayr 2269
        push    ebx
2270
        mov     ebx, net_sockets
2271
 
2272
  .next_socket:
2273
        mov     ebx, [ebx + SOCKET.NextPtr]
2274
        or      ebx, ebx
2275
        jz      .done
2276
        cmp     ebx, eax
2277
        jnz     .next_socket
2278
 
2279
  .done:
2280
        mov     eax, ebx
2281
        test    eax, eax
2282
        pop     ebx
5969 hidnplayr 2283
        ret
3545 hidnplayr 2284
 
5969 hidnplayr 2285
  .error:
5976 hidnplayr 2286
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_check: called with argument 0\n"
5969 hidnplayr 2287
        DEBUGF  DEBUG_NETWORK_ERROR, "stack: 0x%x, 0x%x, 0x%x\n", [esp], [esp+4], [esp+8]
3545 hidnplayr 2288
        ret
2289
 
2290
 
2291
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 2301
align 4
2302
SOCKET_check_owner:
2303
 
3556 hidnplayr 2304
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
3545 hidnplayr 2305
 
2306
        push    ebx
2307
        mov     ebx, [TASK_BASE]
2308
        mov     ebx, [ebx + TASKDATA.pid]
2309
        cmp     [eax + SOCKET.PID], ebx
3711 clevermous 2310
        pop     ebx
3545 hidnplayr 2311
 
2312
        ret
2313
 
2314
 
2315
 
2316
 
5976 hidnplayr 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
;-----------------------------------------------------------------;
3545 hidnplayr 2329
align 4
2330
SOCKET_process_end:
2331
 
4436 hidnplayr 2332
        ret     ; FIXME
2333
 
4056 hidnplayr 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
 
3556 hidnplayr 2339
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
3545 hidnplayr 2340
 
3647 hidnplayr 2341
        pusha
2342
        mov     ecx, socket_mutex
2343
        call    mutex_lock
2344
        popa
2345
 
3545 hidnplayr 2346
        push    ebx
2347
        mov     ebx, net_sockets
2348
 
2349
  .next_socket:
2350
        mov     ebx, [ebx + SOCKET.NextPtr]
2351
  .next_socket_test:
2352
        test    ebx, ebx
2353
        jz      .done
2354
 
2355
        cmp     [ebx + SOCKET.PID], edx
2356
        jne     .next_socket
2357
 
3556 hidnplayr 2358
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
3545 hidnplayr 2359
 
2360
        mov     [ebx + SOCKET.PID], 0
2361
        mov     eax, ebx
2362
        mov     ebx, [ebx + SOCKET.NextPtr]
3648 hidnplayr 2363
 
3545 hidnplayr 2364
        pusha
3652 hidnplayr 2365
        cmp     [eax + SOCKET.Domain], AF_INET4
2366
        jne     .free
2367
 
2368
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2369
        jne     .free
2370
 
4366 hidnplayr 2371
        call    TCP_disconnect
3652 hidnplayr 2372
        jmp     .closed
2373
 
2374
  .free:
2375
        call    SOCKET_free
2376
 
2377
  .closed:
3545 hidnplayr 2378
        popa
2379
        jmp     .next_socket_test
2380
 
2381
  .done:
2382
        pop     ebx
2383
 
3647 hidnplayr 2384
        pusha
2385
        mov     ecx, socket_mutex
2386
        call    mutex_unlock
2387
        popa
2388
 
4056 hidnplayr 2389
  .quickret:
3545 hidnplayr 2390
        ret
2391
 
2392
 
2393
 
2394
 
5976 hidnplayr 2395
;-----------------------------------------------------------------;
2396
;                                                                 ;
2397
; SOCKET_is_connecting: Update socket state.                      ;
2398
;                                                                 ;
2399
;  IN:  eax = socket ptr                                          ;
2400
;                                                                 ;
2401
;  OUT: /                                                         ;
2402
;                                                                 ;
2403
;-----------------------------------------------------------------;
3545 hidnplayr 2404
align 4
2405
SOCKET_is_connecting:
2406
 
3556 hidnplayr 2407
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
3545 hidnplayr 2408
 
4025 hidnplayr 2409
        and     [eax + SOCKET.state], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2410
        or      [eax + SOCKET.state], SS_ISCONNECTING
2411
        ret
3545 hidnplayr 2412
 
2413
 
2414
 
5976 hidnplayr 2415
;-----------------------------------------------------------------;
2416
;                                                                 ;
2417
; SOCKET_is_connected: Update socket state.                       ;
2418
;                                                                 ;
2419
;  IN:  eax = socket ptr                                          ;
2420
;                                                                 ;
2421
;  OUT: /                                                         ;
2422
;                                                                 ;
2423
;-----------------------------------------------------------------;
3545 hidnplayr 2424
align 4
2425
SOCKET_is_connected:
2426
 
3556 hidnplayr 2427
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
3545 hidnplayr 2428
 
3674 hidnplayr 2429
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2430
        or      [eax + SOCKET.state], SS_ISCONNECTED
3545 hidnplayr 2431
        jmp     SOCKET_notify
2432
 
2433
 
2434
 
2435
 
5976 hidnplayr 2436
;-----------------------------------------------------------------;
2437
;                                                                 ;
2438
; SOCKET_is_disconnecting: Update socket state.                   ;
2439
;                                                                 ;
2440
;  IN:  eax = socket ptr                                          ;
2441
;                                                                 ;
2442
;  OUT: /                                                         ;
2443
;                                                                 ;
2444
;-----------------------------------------------------------------;
3545 hidnplayr 2445
align 4
2446
SOCKET_is_disconnecting:
2447
 
3556 hidnplayr 2448
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
3545 hidnplayr 2449
 
3674 hidnplayr 2450
        and     [eax + SOCKET.state], not (SS_ISCONNECTING)
2451
        or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
3545 hidnplayr 2452
        jmp     SOCKET_notify
2453
 
2454
 
2455
 
5976 hidnplayr 2456
;-----------------------------------------------------------------;
2457
;                                                                 ;
2458
; SOCKET_is_disconnected: Update socket state.                    ;
2459
;                                                                 ;
2460
;  IN:  eax = socket ptr                                          ;
2461
;                                                                 ;
2462
;  OUT: /                                                         ;
2463
;                                                                 ;
2464
;-----------------------------------------------------------------;
3545 hidnplayr 2465
align 4
2466
SOCKET_is_disconnected:
2467
 
3556 hidnplayr 2468
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
3545 hidnplayr 2469
 
3674 hidnplayr 2470
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2471
        or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
3545 hidnplayr 2472
        jmp     SOCKET_notify
2473
 
2474
 
2475
 
5976 hidnplayr 2476
;-----------------------------------------------------------------;
2477
;                                                                 ;
2478
; SOCKET_cant_recv_more: Update socket state.                     ;
2479
;                                                                 ;
2480
;  IN:  eax = socket ptr                                          ;
2481
;                                                                 ;
2482
;  OUT: /                                                         ;
2483
;                                                                 ;
2484
;-----------------------------------------------------------------;
3545 hidnplayr 2485
align 4
2486
SOCKET_cant_recv_more:
2487
 
3556 hidnplayr 2488
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3545 hidnplayr 2489
 
3674 hidnplayr 2490
        or      [eax + SOCKET.state], SS_CANTRCVMORE
5976 hidnplayr 2491
        jmp     SOCKET_notify
3545 hidnplayr 2492
 
3565 hidnplayr 2493
 
3545 hidnplayr 2494
 
5976 hidnplayr 2495
;-----------------------------------------------------------------;
2496
;                                                                 ;
2497
; SOCKET_cant_send_more: Update socket state.                     ;
2498
;                                                                 ;
2499
;  IN:  eax = socket ptr                                          ;
2500
;                                                                 ;
2501
;  OUT: /                                                         ;
2502
;                                                                 ;
2503
;-----------------------------------------------------------------;
3545 hidnplayr 2504
align 4
2505
SOCKET_cant_send_more:
2506
 
3556 hidnplayr 2507
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3545 hidnplayr 2508
 
3674 hidnplayr 2509
        or      [eax + SOCKET.state], SS_CANTSENDMORE
3658 hidnplayr 2510
        mov     [eax + SOCKET.snd_proc], .notconn
5976 hidnplayr 2511
        jmp     SOCKET_notify
3545 hidnplayr 2512
 
3658 hidnplayr 2513
  .notconn:
3673 hidnplayr 2514
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2515
        mov     dword[esp+32], -1
5356 serge 2516
        ret