Subversion Repositories Kolibri OS

Rev

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