Subversion Repositories Kolibri OS

Rev

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

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