Subversion Repositories Kolibri OS

Rev

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

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