Subversion Repositories Kolibri OS

Rev

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