Subversion Repositories Kolibri OS

Rev

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

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