Subversion Repositories Kolibri OS

Rev

Rev 9709 | Details | Compare with Previous | Last modification | View Log | RSS feed

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