1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2018-2020. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21-module(socket_server). 22 23-export([ 24 start/0, start/5, 25 start_tcp/0, start_tcp/1, start_tcp/3, 26 start_tcp4/0, start_tcp4/1, start_tcp4/2, 27 start_tcp6/0, start_tcp6/1, start_tcp6/2, 28 start_udp/0, start_udp/1, start_udp/3, 29 start_udp4/0, start_udp4/1, start_udp4/2, 30 start_udp6/0, start_udp6/1, start_udp6/2, 31 start_sctp/0, start_sctp/1 32 ]). 33 34-define(LIB, socket_lib). 35 36-record(manager, {socket, msg, peek, acceptors, handler_id, handlers}). 37-record(acceptor, {id, socket, manager, 38 atimeout = 5000}). 39-record(handler, {socket, peek, msg, type, manager, 40 stimeout = 5000, rtimeout = 5000}). 41 42-define(NUM_ACCEPTORS, 5). 43 44start() -> 45 start_tcp(). 46 47start_tcp() -> 48 start_tcp4(). 49 50start_tcp(Peek) -> 51 start_tcp4(Peek). 52 53start_tcp4() -> 54 start_tcp4(false). 55 56start_tcp4(Peek) -> 57 start_tcp4(false, Peek). 58 59start_tcp4(UseMsg, Peek) -> 60 start_tcp(inet, UseMsg, Peek). 61 62start_tcp6() -> 63 start_tcp6(false). 64 65start_tcp6(Peek) -> 66 start_tcp6(false, Peek). 67 68start_tcp6(UseMsg, Peek) -> 69 start_tcp(inet6, UseMsg, Peek). 70 71start_tcp(Domain, UseMsg, Peek) when is_boolean(UseMsg) andalso is_boolean(Peek) -> 72 start(Domain, stream, tcp, UseMsg, Peek). 73 74start_udp() -> 75 start_udp4(). 76 77start_udp(Peek) -> 78 start_udp4(Peek). 79 80start_udp4() -> 81 start_udp4(false). 82 83start_udp4(Peek) -> 84 start_udp4(false, Peek). 85 86start_udp4(UseMsg, Peek) -> 87 start_udp(inet, UseMsg, Peek). 88 89start_udp6() -> 90 start_udp6(false, false). 91 92start_udp6(Peek) -> 93 start_udp6(false, Peek). 94 95start_udp6(UseMsg, Peek) -> 96 start_udp(inet6, UseMsg, Peek). 97 98start_udp(Domain, UseMsg, Peek) when is_boolean(UseMsg) andalso is_boolean(Peek) -> 99 start(Domain, dgram, udp, UseMsg, Peek). 100 101 102start_sctp() -> 103 start_sctp(inet). 104 105start_sctp(Domain) when ((Domain =:= inet) orelse (Domain =:= inet6)) -> 106 start(Domain, seqpacket, sctp, true, false). 107 108start(Domain, Type, Proto, UseMsg, Peek) -> 109 put(sname, "starter"), 110 i("try start manager"), 111 {Pid, MRef} = manager_start(Domain, Type, Proto, UseMsg, Peek), 112 i("manager (~p) started", [Pid]), 113 loop(Pid, MRef). 114 115loop(Pid, MRef) -> 116 receive 117 {'DOWN', MRef, process, Pid, Reason} -> 118 i("manager process exited: " 119 "~n ~p", [Reason]), 120 ok 121 end. 122 123 124%% ========================================================================= 125 126manager_start(Domain, Type, Proto, UseMsg, Peek) -> 127 spawn_monitor(fun() -> manager_init(Domain, Type, Proto, UseMsg, Peek) end). 128 129manager_start_handler(Pid, Sock) -> 130 manager_request(Pid, {start_handler, Sock}). 131 132manager_stop(Pid, Reason) -> 133 manager_request(Pid, {stop, Reason}). 134 135manager_request(Pid, Request) -> 136 ?LIB:request(manager, Pid, Request). 137 138manager_reply(Pid, Ref, Reply) -> 139 ?LIB:reply(manager, Pid, Ref, Reply). 140 141 142manager_init(Domain, Type, Proto, UseMsg, Peek) -> 143 put(sname, "manager"), 144 do_manager_init(Domain, Type, Proto, UseMsg, Peek). 145 146do_manager_init(Domain, stream = Type, Proto, UseMsg, Peek) -> 147 i("try start acceptor(s)"), 148 {Sock, Acceptors} = manager_stream_init(Domain, Type, Proto), 149 manager_loop(#manager{socket = Sock, 150 msg = UseMsg, 151 peek = Peek, 152 acceptors = Acceptors, 153 handler_id = 1, 154 handlers = []}); 155do_manager_init(Domain, dgram = Type, Proto, UseMsg, Peek) -> 156 i("try open socket"), 157 case socket:open(Domain, Type, Proto) of 158 {ok, Sock} -> 159 F = fun(X) -> case socket:getopt(Sock, socket, X) of 160 {ok, V} -> f("~p", [V]); 161 {error, R} -> f("error: ~p", [R]) 162 end 163 end, 164 i("socket opened (~s,~s,~s): " 165 "~n broadcast: ~s" 166 "~n dontroute: ~s" 167 "~n keepalive: ~s" 168 "~n reuseaddr: ~s" 169 "~n linger: ~s" 170 "~n debug: ~s" 171 "~n prio: ~s" 172 "~n rcvbuf: ~s" 173 "~n rcvtimeo: ~s" 174 "~n sndbuf: ~s" 175 "~n sndtimeo: ~s" 176 "~n => try find (local) address", 177 [F(domain), F(type), F(protocol), 178 F(broadcast), F(dontroute), F(keepalive), F(reuseaddr), F(linger), 179 F(debug), F(priority), 180 F(rcvbuf), F(rcvtimeo), F(sndbuf), F(sndtimeo)]), 181 Addr = which_addr(Domain), 182 SA = #{family => Domain, 183 addr => Addr}, 184 i("try bind to: " 185 "~n ~p", [Addr]), 186 case socket:bind(Sock, SA) of 187 {ok, _P} -> 188 ok; 189 {error, BReason} -> 190 throw({bind, BReason}) 191 end, 192 i("bound to: " 193 "~n ~s" 194 "~n => try start handler", 195 [case socket:sockname(Sock) of 196 {ok, Name} -> f("~p", [Name]); 197 {error, R} -> f("error: ~p", [R]) 198 end]), 199 case handler_start(1, Sock, UseMsg, Peek) of 200 {ok, {Pid, MRef}} -> 201 i("handler (~p) started", [Pid]), 202 handler_continue(Pid), 203 manager_loop(#manager{peek = Peek, 204 msg = UseMsg, 205 handler_id = 2, % Just in case 206 handlers = [{1, Pid, MRef}]}); 207 {error, SReason} -> 208 e("Failed starting handler: " 209 "~n ~p", [SReason]), 210 exit({failed_start_handler, SReason}) 211 end; 212 {error, OReason} -> 213 e("Failed open socket: " 214 "~n ~p", [OReason]), 215 exit({failed_open_socket, OReason}) 216 end; 217do_manager_init(Domain, seqpacket = Type, sctp = Proto, _UseMsg, _Peek) -> 218 %% This is as far as I have got with SCTP at the moment... 219 case socket:open(Domain, Type, Proto) of 220 {ok, Sock} -> 221 i("(sctp) socket opened: " 222 "~n ~p", [Sock]), 223 EXP = fun(_Desc, Expect, Expect) -> 224 Expect; 225 (Desc, Expect, Actual) -> 226 e("Unexpected result ~w: " 227 "~n Expect: ~p" 228 "~n Actual: ~p", [Desc, Expect, Actual]), 229 exit({Desc, Expect, Actual}) 230 end, 231 GO = fun(O) -> case socket:getopt(Sock, sctp, O) of 232 {ok, V} -> f("~p", [V]); 233 {error, R} -> f("error: ~p", [R]) 234 end 235 end, 236 %% ok = socket:setopt(Sock, otp, debug, true), 237 238 i("Miscellaneous options: " 239 "~n associnfo: ~s" 240 "~n autoclose: ~s" 241 "~n disable-fragments: ~s" 242 "~n initmsg: ~s" 243 "~n maxseg: ~s" 244 "~n nodelay: ~s" 245 "~n rtoinfo: ~s", 246 [GO(associnfo), 247 GO(autoclose), 248 GO(disable_fragments), 249 GO(initmsg), 250 GO(maxseg), 251 GO(nodelay), 252 GO(rtoinfo)]), 253 254 Events = #{data_in => true, 255 association => true, 256 address => true, 257 send_failure => true, 258 peer_error => true, 259 shutdown => true, 260 partial_delivery => true, 261 adaptation_layer => true, 262 authentication => true, 263 sender_dry => true}, 264 EXP(set_sctp_events, ok, socket:setopt(Sock, sctp, events, Events)), 265 EXP(close_socket, ok, socket:close(Sock)); 266 {error, Reason} -> 267 exit({failed_open, Reason}) 268 end; 269do_manager_init(Domain, raw = Type, Proto, UseMsg, Peek) when is_integer(Proto) -> 270 do_manager_init(Domain, Type, {raw, Proto}, UseMsg, Peek); 271do_manager_init(Domain, raw = Type, Proto, _UseMsg, _Peek) -> 272 case socket:open(Domain, Type, Proto) of 273 {ok, Sock} -> 274 i("(sctp) socket opened: " 275 "~n ~p", [Sock]), 276 socket:close(Sock); 277 {error, Reason} -> 278 exit({failed_open, Reason}) 279 end. 280 281 282 283manager_stream_init(Domain, Type, Proto) -> 284 i("try (socket) open"), 285 Sock = case socket:open(Domain, Type, Proto) of 286 {ok, S} -> 287 S; 288 {error, OReason} -> 289 throw({open, OReason}) 290 end, 291 F = fun(X) -> case socket:getopt(Sock, socket, X) of 292 {ok, V} -> f("~p", [V]); 293 {error, R} -> f("error: ~p", [R]) 294 end 295 end, 296 i("(socket) open (~s,~s,~s): " 297 "~n debug: ~s" 298 "~n prio: ~s" 299 "~n => try find (local) address", 300 [F(domain), F(type), F(protocol), F(debug), F(priority)]), 301 Addr = which_addr(Domain), 302 SA = #{family => Domain, 303 addr => Addr}, 304 i("found: " 305 "~n ~p" 306 "~n => try (socket) bind", [Addr]), 307 %% ok = socket:setopt(Sock, otp, debug, true), 308 %% ok = socket:setopt(Sock, socket, debug, 1), %% must have rights!! 309 Port = case socket:bind(Sock, SA) of 310 {ok, P} -> 311 %% ok = socket:setopt(Sock, socket, debug, 0), %% must have rights!! 312 %% ok = socket:setopt(Sock, otp, debug, false), 313 P; 314 {error, BReason} -> 315 throw({bind, BReason}) 316 end, 317 i("bound to: " 318 "~n ~p" 319 "~n => try (socket) listen (acceptconn: ~s)", 320 [Port, F(acceptconn)]), 321 case socket:listen(Sock) of 322 ok -> 323 i("listening (acceptconn: ~s)", 324 [F(acceptconn)]), 325 manager_stream_init(Sock, 1, ?NUM_ACCEPTORS, []); 326 {error, LReason} -> 327 throw({listen, LReason}) 328 end. 329 330which_addr(Domain) -> 331 Iflist = case inet:getifaddrs() of 332 {ok, IFL} -> 333 IFL; 334 {error, Reason} -> 335 throw({inet,getifaddrs,Reason}) 336 end, 337 which_addr(Domain, Iflist). 338 339which_addr(_Domain, []) -> 340 throw(no_address); 341which_addr(Domain, [{Name, IFO}|_IFL]) when (Name =/= "lo") -> 342 which_addr2(Domain, IFO); 343which_addr(Domain, [_|IFL]) -> 344 which_addr(Domain, IFL). 345 346which_addr2(_, []) -> 347 throw(no_address); 348which_addr2(inet = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 4) -> 349 Addr; 350which_addr2(inet6 = _Domain, [{addr, Addr}|_IFO]) when (size(Addr) =:= 8) -> 351 Addr; 352which_addr2(Domain, [_|IFO]) -> 353 which_addr2(Domain, IFO). 354 355 356manager_stream_init(Sock, ID, NumAcceptors, Acc) 357 when (NumAcceptors > 0) -> 358 i("try start acceptor"), 359 case acceptor_start(Sock, ID) of 360 {ok, {Pid, MRef}} -> 361 i("acceptor ~w (~p) started", [ID, Pid]), 362 ?LIB:sleep(2000), 363 manager_stream_init(Sock, ID+1, NumAcceptors-1, 364 [{ID, Pid, MRef}|Acc]); 365 {error, Reason} -> 366 exit({failed_starting_acceptor, Reason}) 367 end; 368manager_stream_init(Sock, _ID, 0, Acc) -> 369 %% Req = {kill_acceptor, length(Acc)}, % Last in the queue 370 %% Req = {kill_acceptor, 3}, % In the "middle" of the queue 371 %% Req = {kill_acceptor, 2}, % The first in the queue 372 %% Req = {kill_acceptor, 1}, % Current acceptor 373 %% Msg = {manager, self(), make_ref(), Req}, 374 %% erlang:send_after(timer:seconds(10), self(), Msg), 375 {Sock, lists:reverse(Acc)}. 376 377 378manager_loop(M) -> 379 receive 380 {'DOWN', MRef, process, Pid, Reason} -> 381 M2 = manager_handle_down(M, MRef, Pid, Reason), 382 manager_loop(M2); 383 384 {manager, Pid, Ref, Request} -> 385 M2 = manager_handle_request(M, Pid, Ref, Request), 386 manager_loop(M2) 387 end. 388 389 390manager_handle_down(#manager{acceptors = Acceptors, 391 handlers = Handlers} = M, MRef, Pid, Reason) -> 392 case lists:keysearch(Pid, 2, Acceptors) of 393 {value, {ID, Pid, MRef}} when (Reason =:= normal) -> 394 i("acceptor ~w exited (normally)", [ID]), 395 case lists:keydelete(Pid, 2, Acceptors) of 396 [] -> 397 %% We are done 398 i("the last acceptor - we are done"), 399 exit(normal); 400 Acceptors2 -> 401 M#manager{acceptors = Acceptors2} 402 end; 403 {value, {ID, Pid, MRef}} -> 404 e("acceptor ~w crashed: " 405 "~n ~p", [ID, Reason]), 406 exit({acceptor_died, Reason}); 407 408 false -> %% handler! 409 if 410 (Reason =/= normal) -> 411 e("handler ~p died: " 412 "~n ~p", [Pid, Reason]); 413 true -> 414 i("handler ~p terminated", [Pid]) 415 end, 416 Handlers2 = lists:keydelete(Pid, 2, Handlers), 417 M#manager{handlers = Handlers2} 418 end. 419 420 421manager_handle_request(#manager{peek = Peek, 422 msg = UseMsg, 423 handler_id = HID, 424 handlers = Handlers} = M, Pid, Ref, 425 {start_handler, Sock}) -> 426 i("try start handler (~w)", [HID]), 427 case handler_start(HID, Sock, UseMsg, Peek) of 428 {ok, {HPid, HMRef}} -> 429 i("handler ~w started", [HID]), 430 manager_reply(Pid, Ref, {ok, HPid}), 431 M#manager{handler_id = HID+1, 432 handlers = [{HID, HPid, HMRef}|Handlers]}; 433 {error, Reason} = ERROR -> 434 e("Failed starting new handler: " 435 "~n Sock: ~p" 436 "~n Reason: ~p", [Sock, Reason]), 437 manager_reply(Pid, Ref, ERROR), 438 M 439 end; 440manager_handle_request(#manager{socket = Sock, 441 acceptors = [{AID, APid, AMRef}]} = M, _Pid, _Ref, 442 {kill_acceptor, AID}) -> 443 i("try kill (only remeining) acceptor ~w", [AID]), 444 socket:setopt(Sock, otp, debug, true), 445 manager_stop_acceptor(APid, AMRef, AID, kill), 446 M#manager{acceptors = []}; 447manager_handle_request(#manager{socket = Sock, 448 acceptors = Acceptors} = M, _Pid, _Ref, 449 {kill_acceptor, AID}) -> 450 i("try kill acceptor ~w", [AID]), 451 case lists:keysearch(AID, 1, Acceptors) of 452 {value, {AID, APid, AMRef}} -> 453 socket:setopt(Sock, otp, debug, true), 454 manager_stop_acceptor(APid, AMRef, AID, kill), 455 Acceptors2 = lists:keydelete(AID, 1, Acceptors), 456 M#manager{acceptors = Acceptors2}; 457 false -> 458 e("no such acceptor"), 459 M 460 end; 461manager_handle_request(#manager{acceptors = Acceptors, 462 handlers = Handlers}, Pid, Ref, 463 {stop, Reason}) -> 464 i("stop"), 465 manager_reply(Pid, Ref, ok), 466 manager_stop_handlers(Handlers, Reason), 467 manager_stop_acceptors(Acceptors, Reason), 468 i("stopped", []), 469 exit(Reason). 470 471manager_stop_acceptors(Acceptors, Reason) -> 472 lists:foreach(fun({ID,P,M}) -> 473 manager_stop_acceptor(P, M, ID, Reason) 474 end, Acceptors). 475 476manager_stop_acceptor(Pid, MRef, ID, Reason) -> 477 i("try stop acceptor ~w (~p): ~p", [ID, Pid, Reason]), 478 erlang:demonitor(MRef, [flush]), 479 acceptor_stop(Pid, Reason), 480 ok. 481 482manager_stop_handlers(Handlers, Reason) -> 483 lists:foreach(fun({ID,P,M}) -> 484 manager_stop_handler(P, M, ID, Reason) 485 end, Handlers). 486 487manager_stop_handler(Pid, MRef, ID, Reason) -> 488 i("try stop handler ~w (~p): ~p", [ID, Pid, Reason]), 489 erlang:demonitor(MRef, [flush]), 490 handler_stop(Pid, Reason), 491 ok. 492 493 494 495%% ========================================================================= 496 497acceptor_start(Sock, ID) -> 498 Self = self(), 499 A = {Pid, _} = spawn_monitor(fun() -> 500 acceptor_init(Self, Sock, ID) 501 end), 502 receive 503 {acceptor, Pid, ok} -> 504 {ok, A}; 505 {acceptor, Pid, {error, _} = Error} -> 506 exit(Pid, kill), % Just in case 507 Error; 508 {'DOWN', _MRef, process, Pid, Reason} -> 509 {error, {crashed, Reason}} 510 end. 511 512acceptor_stop(Pid, _Reason) -> 513 %% acceptor_request(Pid, {stop, Reason}). 514 exit(Pid, kill). 515 516%% acceptor_request(Pid, Request) -> 517%% request(acceptor, Pid, Request). 518 519%% acceptor_reply(Pid, Ref, Reply) -> 520%% reply(acceptor, Pid, Ref, Reply). 521 522 523acceptor_init(Manager, Sock, ID) -> 524 put(sname, f("acceptor[~w]", [ID])), 525 Manager ! {acceptor, self(), ok}, 526 %% ok = socket:setopt(Sock, otp, debug, true), 527 acceptor_loop(#acceptor{id = ID, 528 manager = Manager, 529 socket = Sock}). 530 531acceptor_loop(#acceptor{socket = LSock, atimeout = Timeout} = A) -> 532 i("try accept"), 533 case socket:accept(LSock, Timeout) of 534 {ok, Sock} -> 535 i("accepted: " 536 "~n ~p" 537 "~nwhen" 538 "~n ~p", [Sock, socket:info()]), 539 case acceptor_handle_accept_success(A, Sock) of 540 ok -> 541 acceptor_loop(A); 542 {error, Reason} -> 543 e("Failed starting handler: " 544 "~n ~p", [Reason]), 545 socket:close(Sock), 546 exit({failed_starting_handler, Reason}) 547 end; 548 {error, timeout} -> 549 i("timeout"), 550 acceptor_loop(A); 551 {error, Reason} -> 552 e("accept failure: " 553 "~n ~p", [Reason]), 554 exit({accept, Reason}) 555 end. 556 557acceptor_handle_accept_success(#acceptor{manager = Manager}, Sock) -> 558 i("try start handler for peer" 559 "~n ~p", [case socket:peername(Sock) of 560 {ok, Peer} -> Peer; 561 {error, _} = E -> E 562 end]), 563 case manager_start_handler(Manager, Sock) of 564 {ok, Pid} -> 565 i("handler (~p) started - now change 'ownership'", [Pid]), 566 case socket:setopt(Sock, otp, controlling_process, Pid) of 567 ok -> 568 %% Normally we should have a msgs collection here 569 %% (of messages we receive before the control was 570 %% handled over to Handler), but since we don't 571 %% have active implemented yet... 572 i("new handler (~p) now controlling process", [Pid]), 573 handler_continue(Pid), 574 ok; 575 {error, _} = ERROR -> 576 exit(Pid, kill), 577 ERROR 578 end; 579 {error, Reason2} -> 580 e("failed starting handler: " 581 "~n (new) Socket: ~p" 582 "~n Reason: ~p", [Sock, Reason2]), 583 exit({failed_starting_handler, Reason2}) 584 end. 585 586 587 588%% ========================================================================= 589 590handler_start(ID, Sock, UseMsg, Peek) -> 591 Self = self(), 592 H = {Pid, _} = spawn_monitor(fun() -> 593 handler_init(Self, ID, UseMsg, Peek, Sock) 594 end), 595 receive 596 {handler, Pid, ok} -> 597 {ok, H}; 598 {handler, Pid, {error, _} = ERROR} -> 599 exit(Pid, kill), % Just in case 600 ERROR 601 end. 602 603handler_stop(Pid, _Reason) -> 604 %% handler_request(Pid, {stop, Reason}). 605 exit(Pid, kill). 606 607handler_continue(Pid) -> 608 handler_request(Pid, continue). 609 610handler_request(Pid, Request) -> 611 ?LIB:request(handler, Pid, Request). 612 613handler_reply(Pid, Ref, Reply) -> 614 ?LIB:reply(handler, Pid, Ref, Reply). 615 616 617handler_init(Manager, ID, Msg, Peek, Sock) -> 618 put(sname, f("handler:~w", [ID])), 619 i("starting"), 620 Manager ! {handler, self(), ok}, 621 receive 622 {handler, Pid, Ref, continue} -> 623 i("got continue"), 624 handler_reply(Pid, Ref, ok), 625 G = fun(L, O) -> case socket:getopt(Sock, L, O) of 626 {ok, Val} -> 627 f("~p", [Val]); 628 {error, R} when is_atom(R) -> 629 f("error: ~w", [R]); 630 {error, {T, R}} when is_atom(T) -> 631 f("error: ~w, ~p", [T, R]); 632 {error, R} -> 633 f("error: ~p", [R]) 634 end 635 end, 636 GSO = fun(O) -> G(socket, O) end, 637 GIP4 = fun(O) -> G(ip, O) end, 638 GIP6 = fun(O) -> G(ipv6, O) end, 639 {ok, Domain} = socket:getopt(Sock, socket, domain), 640 {ok, Type} = socket:getopt(Sock, socket, type), 641 {ok, Proto} = socket:getopt(Sock, socket, protocol), 642 B2D = GSO(bindtodevice), 643 RA = GSO(reuseaddr), 644 RP = GSO(reuseport), 645 OOBI = GSO(oobinline), 646 RcvBuf = GSO(rcvbuf), 647 RcvLW = GSO(rcvlowat), 648 RcvTO = GSO(rcvtimeo), 649 SndBuf = GSO(sndbuf), 650 SndLW = GSO(sndlowat), 651 SndTO = GSO(sndtimeo), 652 Linger = GSO(linger), 653 Timestamp = GSO(timestamp), 654 FreeBind = GIP4(freebind), 655 MTU = GIP4(mtu), 656 MTUDisc = GIP4(mtu_discover), 657 MALL = GIP4(multicast_all), 658 MIF4 = GIP4(multicast_if), 659 MLoop4 = GIP4(multicast_loop), 660 MTTL = GIP4(multicast_ttl), 661 NF = GIP4(nodefrag), % raw only 662 PktInfo = GIP4(pktinfo), % dgram only 663 RecvErr4 = GIP4(recverr), 664 RecvIF = GIP4(recvif), % Only dgram and raw (and FreeBSD) 665 RecvOPTS = GIP4(recvopts), % Not stream 666 RecvOrigDstAddr = GIP4(recvorigdstaddr), 667 RecvTOS = GIP4(recvtos), 668 RecvTTL = GIP4(recvttl), % not stream 669 RetOpts = GIP4(retopts), % not stream 670 SendSrcAddr = GIP4(sendsrcaddr), 671 TOS = GIP4(tos), 672 Transparent = GIP4(transparent), 673 TTL = GIP4(ttl), 674 MHops = GIP6(multicast_hops), 675 MIF6 = GIP6(multicast_if), % Only dgram and raw 676 MLoop6 = GIP6(multicast_loop), 677 RecvErr6 = GIP6(recverr), 678 RecvPktInfo = GIP6(recvpktinfo), 679 RtHdr = GIP6(rthdr), 680 AuthHdr = GIP6(authhdr), 681 HopLimit = GIP6(hoplimit), 682 HopOpts = GIP6(hopopts), 683 DstOpts = GIP6(dstopts), 684 FlowInfo = GIP6(flowinfo), 685 UHops = GIP6(unicast_hops), 686 i("got continue when: " 687 "~n (socket) Domain: ~p" 688 "~n (socket) Type: ~p" 689 "~n (socket) Protocol: ~p" 690 "~n (socket) Reuse Address: ~s" 691 "~n (socket) Reuse Port: ~s" 692 "~n (socket) Bind To Device: ~s" 693 "~n (socket) OOBInline: ~s" 694 "~n (socket) RcvBuf: ~s" 695 "~n (socket) RcvLW: ~s" 696 "~n (socket) RcvTO: ~s" 697 "~n (socket) SndBuf: ~s" 698 "~n (socket) SndLW: ~s" 699 "~n (socket) SndTO: ~s" 700 "~n (socket) Linger: ~s" 701 "~n (socket) Timestamp: ~s" 702 "~n (ip) FreeBind: ~s" 703 "~n (ip) MTU: ~s" 704 "~n (ip) MTU Discovery: ~s" 705 "~n (ip) Multicast ALL: ~s" 706 "~n (ip) Multicast IF: ~s" 707 "~n (ip) Multicast Loop: ~s" 708 "~n (ip) Multicast TTL: ~s" 709 "~n (ip) Node Frag: ~s" 710 "~n (ip) Pkt Info: ~s" 711 "~n (ip) Recv Err: ~s" 712 "~n (ip) Recv IF: ~s" 713 "~n (ip) Recv OPTS: ~s" 714 "~n (ip) Recv Orig Dst Addr: ~s" 715 "~n (ip) Recv TOS: ~s" 716 "~n (ip) Recv TTL: ~s" 717 "~n (ip) Ret Opts: ~s" 718 "~n (ip) Send Src Addr: ~s" 719 "~n (ip) TOS: ~s" 720 "~n (ip) Transparent: ~s" 721 "~n (ip) TTL: ~s" 722 "~n (ipv6) Multicast Hops: ~s" 723 "~n (ipv6) Multicast IF: ~s" 724 "~n (ipv6) Multicast Loop: ~s" 725 "~n (ipv6) Recv Err: ~s" 726 "~n (ipv6) Recv Pkt Info: ~s" 727 "~n (ipv6) RT Hdr: ~s" 728 "~n (ipv6) Auth Hdr: ~s" 729 "~n (ipv6) Hop Limit: ~s" 730 "~n (ipv6) Hop Opts: ~s" 731 "~n (ipv6) Dst Opts: ~s" 732 "~n (ipv6) Flow Info: ~s" 733 "~n (ipv6) Unicast Hops: ~s", 734 [Domain, Type, Proto, 735 RA, RP, B2D, OOBI, 736 RcvBuf, RcvLW, RcvTO, SndBuf, SndLW, SndTO, 737 Linger, Timestamp, 738 FreeBind, MTU, MTUDisc, MALL, MIF4, MLoop4, MTTL, 739 NF, PktInfo,RecvErr4, 740 RecvIF, RecvOPTS, RecvOrigDstAddr, RecvTOS, RecvTTL, RetOpts, 741 SendSrcAddr, TOS, Transparent, TTL, 742 MHops, MIF6, MLoop6, RecvErr6, RecvPktInfo, 743 RtHdr, AuthHdr, HopLimit, HopOpts, DstOpts, FlowInfo, 744 UHops]), 745 746 %% ok = socket:setopt(Sock, otp, debug, true), 747 %% case socket:getopt(Sock, 0, {13, int}) of 748 %% {ok, Val} -> 749 %% i("PktOpts ok: ~p", [Val]); 750 %% {error, Reason} -> 751 %% e("PktOpts err: ~p", [Reason]) 752 %% end, 753 %% ok = socket:setopt(Sock, otp, debug, false), 754 SSO = fun(O, V) -> soso(Sock, O, V) end, 755 SIP4 = 756 fun(O, V) -> 757 if 758 (Type =:= dgram) -> 759 ok = soip(Sock, O, V); 760 true -> 761 ok 762 end 763 end, 764 SSO(timestamp, true), 765 SIP4(pktinfo, true), 766 ok = soip(Sock, recvtos, true), 767 SIP4(recvttl, true), 768 ok = soip(Sock, recvorigdstaddr, true), 769 770 handler_loop(#handler{msg = Msg, 771 peek = Peek, 772 manager = Manager, 773 type = Type, 774 socket = Sock}) 775 end. 776 777so(Sock, Lvl, Opt, Val) -> 778 ok = socket:setopt(Sock, Lvl, Opt, Val). 779 780soso(Sock, Opt, Val) -> 781 so(Sock, socket, Opt, Val). 782 783soip(Sock, Opt, Val) -> 784 so(Sock, ip, Opt, Val). 785 786%% soipv6(Sock, Opt, Val) -> 787%% so(Sock, ipv6, Opt, Val). 788 789handler_loop(H) -> 790 i("try read message"), 791 case recv(H) of 792 {ok, {Source, Msg}} -> 793 i("received ~w bytes of data~s", 794 [size(Msg), case Source of 795 undefined -> ""; 796 _ -> f(" from:~n ~p", [Source]) 797 end]), 798 case ?LIB:dec_msg(Msg) of 799 {request, N, Req} -> 800 i("received request ~w: " 801 "~n ~p", [N, Req]), 802 Reply = ?LIB:enc_rep_msg(N, "hoppsan"), 803 case send(H, Reply, Source) of 804 ok -> 805 i("successfully sent reply ~w", [N]), 806 handler_loop(H); 807 {error, SReason} -> 808 e("failed sending reply ~w:" 809 "~n ~p", [N, SReason]), 810 exit({failed_sending_reply, SReason}) 811 end 812 end; 813 814 {error, closed} -> 815 i("closed when" 816 "~n ~p", [socket:info()]), 817 exit(normal); 818 819 {error, RReason} -> 820 e("failed reading request: " 821 "~n ~p", [RReason]), 822 exit({failed_reading_request, RReason}) 823 end. 824 825 826recv(#handler{peek = true, socket = Sock, type = stream}) -> 827 peek_recv(Sock); 828recv(#handler{socket = Sock, msg = true, type = stream}) -> 829 case socket:recvmsg(Sock) of 830 {ok, #{addr := undefined = Source, 831 iov := [Data], 832 ctrl := CMsgHdrs, 833 flags := Flags}} -> 834 i("received message: " 835 "~n CMsgHdrs: ~p" 836 "~n Flags: ~p", [CMsgHdrs, Flags]), 837 {ok, {Source, Data}}; 838 {ok, X} -> 839 e("received *unexpected* message: " 840 "~n ~p", [X]), 841 {error, {unexpected, X}}; 842 {error, _} = ERROR -> 843 ERROR 844 end; 845recv(#handler{socket = Sock, msg = true, type = dgram}) -> 846 case socket:recvmsg(Sock) of 847 {ok, #{addr := Source, 848 iov := [Data], 849 ctrl := CMsgHdrs, 850 flags := Flags}} -> 851 i("received message: " 852 "~n CMsgHdrs: ~p" 853 "~n Flags: ~p", [CMsgHdrs, Flags]), 854 {ok, {Source, Data}}; 855 {ok, X} -> 856 {error, {unexpected, X}}; 857 {error, _} = ERROR -> 858 ERROR 859 end; 860recv(#handler{peek = false, socket = Sock, type = stream}) -> 861 do_recv(Sock); 862recv(#handler{peek = Peek, socket = Sock, type = dgram}) 863 when (Peek =:= true) -> 864 %% ok = socket:setopt(Sock, otp, debug, true), 865 RES = peek_recvfrom(Sock, 5), 866 %% ok = socket:setopt(Sock, otp, debug, false), 867 RES; 868recv(#handler{peek = Peek, socket = Sock, type = dgram}) 869 when (Peek =:= false) -> 870 %% ok = socket:setopt(Sock, otp, debug, true), 871 socket:recvfrom(Sock). 872 873do_recv(Sock) -> 874 case socket:recv(Sock) of 875 {ok, Msg} -> 876 {ok, {undefined, Msg}}; 877 {error, _} = ERROR -> 878 ERROR 879 end. 880 881peek_recv(Sock) -> 882 i("try peek on the message type (expect request)"), 883 Type = ?LIB:req(), 884 case socket:recv(Sock, 4, [peek]) of 885 {ok, <<Type:32>>} -> 886 i("was request - do proper recv"), 887 do_recv(Sock); 888 {error, _} = ERROR -> 889 ERROR 890 end. 891 892peek_recvfrom(Sock, BufSz) -> 893 i("try peek recvfrom with buffer size ~w", [BufSz]), 894 case socket:recvfrom(Sock, BufSz, [peek]) of 895 {ok, {_Source, Msg}} when (BufSz =:= size(Msg)) -> 896 %% i("we filled the buffer: " 897 %% "~n ~p", [Msg]), 898 %% It *may not* fit => try again with double size 899 peek_recvfrom(Sock, BufSz*2); 900 {ok, _} -> 901 %% It fits => read for real 902 i("we did *not* fill the buffer - do the 'real' read"), 903 socket:recvfrom(Sock); 904 {error, _} = ERROR -> 905 ERROR 906 end. 907 908 909send(#handler{socket = Sock, msg = true, type = stream, stimeout = Timeout}, 910 Msg, _) -> 911 CMsgHdr = #{level => ip, type => tos, data => reliability}, 912 CMsgHdrs = [CMsgHdr], 913 MsgHdr = #{iov => [Msg], ctrl => CMsgHdrs}, 914 %% socket:setopt(Sock, otp, debug, true), 915 Res = socket:sendmsg(Sock, MsgHdr, Timeout), 916 %% socket:setopt(Sock, otp, debug, false), 917 Res; 918send(#handler{socket = Sock, type = stream, stimeout = Timeout}, Msg, _) -> 919 socket:send(Sock, Msg, Timeout); 920send(#handler{socket = Sock, msg = true, type = dgram, stimeout = Timeout}, 921 Msg, Dest) -> 922 CMsgHdr = #{level => ip, type => tos, data => reliability}, 923 CMsgHdrs = [CMsgHdr], 924 MsgHdr = #{addr => Dest, 925 ctrl => CMsgHdrs, 926 iov => [Msg]}, 927 %% ok = socket:setopt(Sock, otp, debug, true), 928 Res = socket:sendmsg(Sock, MsgHdr, Timeout), 929 %% ok = socket:setopt(Sock, otp, debug, false), 930 Res; 931send(#handler{socket = Sock, type = dgram, stimeout = Timeout}, Msg, Dest) -> 932 socket:sendto(Sock, Msg, Dest, Timeout). 933 934%% filler() -> 935%% list_to_binary(lists:duplicate(2048, " FILLER ")). 936 937 938 939%% ========================================================================= 940 941f(F, A) -> 942 ?LIB:f(F, A). 943 944e(F) -> 945 e(F, []). 946e(F, A) -> 947 ?LIB:e(F, A). 948 949i(F) -> 950 ?LIB:i(F). 951 952i(F, A) -> 953 ?LIB:i(F, A). 954 955