4373 ^ self setSocketOption:#'TCP_NODELAY' argument:aBoolean argument:nil. |
4373 ^ self setSocketOption:#'TCP_NODELAY' argument:aBoolean argument:nil. |
4374 ! ! |
4374 ! ! |
4375 |
4375 |
4376 !Socket methodsFor:'support websocket'! |
4376 !Socket methodsFor:'support websocket'! |
4377 |
4377 |
4378 nonBlockingNextPutAll:someBytes |
4378 blockingNextPutAllForNonBlockingSocket:someBytes |
4379 "using #primNonBlockingNextPutAll: |
4379 "explanation of the method name: |
4380 because #nextPutAll: handles WSAEWOULDBLOCK / EWOULDBLOCK incorrect (at least for windows) |
4380 blocking -> this method blocks its STX process until all bytes have been written |
4381 only called by WebSocketStream #criticalSocketNextPutAll:" |
4381 ForNonBlockingSocket -> this method only works with non-blocking sockets |
|
4382 |
|
4383 the write is done within the current thread, |
|
4384 but the primitiv #send returns because the socket is non-blocking (in case of would block). |
|
4385 of cause if you write big data at once and the socket never would block, STX will freeze, |
|
4386 so please split big data into small packages" |
|
4387 |
|
4388 "PROBLEM \ BUG: |
|
4389 currently STX will freeze when writing and reading concurrently on the same blocking socket from both ends. |
|
4390 even when all those writers and readers have their own thread (by calling via __NOINT_CALL). |
|
4391 |
|
4392 WORKAROUND (or Other Concept): |
|
4393 using a non-blocking socket |
|
4394 |
|
4395 NEW PROBLEM: |
|
4396 with non-blocking sockets you can not use the default #nextPut: |
|
4397 because #nextPut: ends up in __NOINT_CALL('send') and probably due to until now not supported non-blocking sockets, |
|
4398 it does not set __threadErrno correctly to WOULDBLOCK in case of would block. |
|
4399 so by using default #nextPut: with an non-blocking socket you will miss some bytes or |
|
4400 falsely get an error instead of WOULBLOCK |
|
4401 |
|
4402 NEXT WORKAROUND: |
|
4403 use a your own #nextPut: method (#blockingNextPutAllForNonBlockingSocket:) and handle WOULDBLOCK correctly |
|
4404 |
|
4405 Notes: |
|
4406 - all sockets under windows are created as blocking sockets by default |
|
4407 - there is NO query in windows to ask if a socket is blocking or non-blocking" |
4382 |
4408 |
4383 |bytes countRemainingBytesToWrite result| |
4409 |bytes countRemainingBytesToWrite result| |
4384 |
4410 |
4385 OperatingSystem isMSWINDOWSlike ifFalse:[ |
4411 OperatingSystem isMSWINDOWSlike ifFalse:[ |
4386 "this method supports non blocking socket for windows, |
4412 "this method supports non blocking socket for windows, |
4404 |
4430 |
4405 "/ timeout does not matter, we wait indefinitely (due to loop) |
4431 "/ timeout does not matter, we wait indefinitely (due to loop) |
4406 self writeWaitWithTimeoutMs:1000. |
4432 self writeWaitWithTimeoutMs:1000. |
4407 ]. |
4433 ]. |
4408 |
4434 |
4409 "Created: / 30-01-2020 / 16:35:08 / Stefan Reise" |
4435 "Created: / 05-03-2020 / 10:35:54 / Stefan Reise" |
4410 "Modified (format): / 06-02-2020 / 13:18:59 / Stefan Reise" |
4436 ! |
4411 "Modified (comment): / 03-03-2020 / 15:25:26 / Stefan Vogel" |
4437 |
4412 ! |
4438 setNonBlocking |
4413 |
4439 "DO NO move this functionality into Win32OperatingSystem #setBlocking:fd:, |
4414 primNonBlockingNextPutAll:someBytes |
4440 because it will not work correctly, caused by the following problems. |
4415 "using #primNonBlockingNextPutAll: |
4441 and even if the problems has been fixed, it would change the behavior for all sockets (not only websockets)" |
4416 because #nextPutAll: handles WSAEWOULDBLOCK / EWOULDBLOCK incorrect (at least for windows) |
4442 |
4417 only called by WebSocketStream #criticalSocketNextPutAll:" |
4443 "PROBLEM \ BUG: |
|
4444 currently STX will freeze when writing and reading concurrently on the same blocking socket from both ends. |
|
4445 even when all those writers and readers have their own thread (by calling via __NOINT_CALL). |
|
4446 |
|
4447 WORKAROUND (or Other Concept): |
|
4448 using a non-blocking socket |
|
4449 |
|
4450 NEW PROBLEM: |
|
4451 with non-blocking sockets you can not use the default #nextPut: |
|
4452 because #nextPut: ends up in __NOINT_CALL('send') and probably due to until now not supported non-blocking sockets, |
|
4453 it does not set __threadErrno correctly to WOULDBLOCK in case of would block. |
|
4454 so by using default #nextPut: with an non-blocking socket you will miss some bytes or |
|
4455 falsely get an error instead of WOULBLOCK |
|
4456 |
|
4457 NEXT WORKAROUND: |
|
4458 use a your own #nextPut: method (#blockingNextPutAllForNonBlockingSocket:) and handle WOULDBLOCK correctly |
|
4459 |
|
4460 Notes: |
|
4461 - all sockets under windows are created as blocking sockets by default |
|
4462 - there is NO query in windows to ask if a socket is blocking or non-blocking" |
|
4463 |
|
4464 OperatingSystem isMSWINDOWSlike ifFalse:[ |
|
4465 "/ this method is for windows os only |
|
4466 ^ self |
|
4467 ]. |
|
4468 |
|
4469 %{ |
|
4470 # ifdef __win32__ |
|
4471 OBJ fp = __INST(handle); |
|
4472 |
|
4473 // ALWAYS check for proper arguments, please |
|
4474 if (fp != NULL) { |
|
4475 int result; |
|
4476 u_long nonBlocking = 1; |
|
4477 SOCKET socket = SOCKET_FROM_FILE_OBJECT(fp); |
|
4478 |
|
4479 result = ioctlsocket(socket, FIONBIO, &nonBlocking); |
|
4480 if (result == SOCKET_ERROR) { |
|
4481 console_fprintf(stderr, "Win32OS [info]: ioctlsocket failed with %d\n", WSAGetLastError()); |
|
4482 RETURN(false); |
|
4483 } |
|
4484 |
|
4485 RETURN(true); |
|
4486 } |
|
4487 #endif // __win32__ |
|
4488 %}. |
|
4489 |
|
4490 self primitiveFailed. |
|
4491 |
|
4492 "Modified: / 03-03-2020 / 15:29:26 / Stefan Vogel" |
|
4493 "Modified: / 05-03-2020 / 10:37:12 / Stefan Reise" |
|
4494 ! |
|
4495 |
|
4496 systemBlockingNextPutAll:someBytes |
|
4497 "explanation of the method name: |
|
4498 systemBlocking -> this method blocks the entire STX |
|
4499 until all bytes have been written or until the socket would block |
|
4500 |
|
4501 so please split big data into small packages" |
|
4502 |
|
4503 "PROBLEM \ BUG: |
|
4504 currently STX will freeze when writing and reading concurrently on the same blocking socket from both ends. |
|
4505 even when all those writers and readers have their own thread (by calling via __NOINT_CALL). |
|
4506 |
|
4507 WORKAROUND (or Other Concept): |
|
4508 using a non-blocking socket |
|
4509 |
|
4510 NEW PROBLEM: |
|
4511 with non-blocking sockets you can not use the default #nextPut: |
|
4512 because #nextPut: ends up in __NOINT_CALL('send') and probably due to until now not supported non-blocking sockets, |
|
4513 it does not set __threadErrno correctly to WOULDBLOCK in case of would block. |
|
4514 so by using default #nextPut: with an non-blocking socket you will miss some bytes or |
|
4515 falsely get an error instead of WOULBLOCK |
|
4516 |
|
4517 NEXT WORKAROUND: |
|
4518 use a your own #nextPut: method (#blockingNextPutAllForNonBlockingSocket:) and handle WOULDBLOCK correctly |
|
4519 |
|
4520 Notes: |
|
4521 - all sockets under windows are created as blocking sockets by default |
|
4522 - there is NO query in windows to ask if a socket is blocking or non-blocking" |
4418 |
4523 |
4419 |bytes byteLength returnValue wsaError| |
4524 |bytes byteLength returnValue wsaError| |
4420 |
4525 |
4421 OperatingSystem isMSWINDOWSlike ifFalse:[ |
4526 OperatingSystem isMSWINDOWSlike ifFalse:[ |
4422 self error:'this method is for windows os only'. |
4527 self error:'this method is for windows os only'. |
4466 WriteError raiseWith:wsaError. |
4572 WriteError raiseWith:wsaError. |
4467 ]. |
4573 ]. |
4468 |
4574 |
4469 ^ returnValue |
4575 ^ returnValue |
4470 |
4576 |
4471 "Modified: / 03-03-2020 / 15:29:09 / Stefan Vogel" |
4577 "Created: / 05-03-2020 / 10:48:56 / Stefan Reise" |
4472 ! |
|
4473 |
|
4474 setNonBlocking |
|
4475 "using #setNonBlocking |
|
4476 because implementing and using Win32OperatingSystem #setBlocking:fd: |
|
4477 would reset to blocking (see senders of #blocking:) |
|
4478 and we need the socket to be non-blocking forever |
|
4479 only called by WebSocketStream #criticalSocketNextPutAll:" |
|
4480 |
|
4481 OperatingSystem isMSWINDOWSlike ifFalse:[ |
|
4482 "/ this method is for windows os only |
|
4483 ^ self |
|
4484 ]. |
|
4485 |
|
4486 %{ |
|
4487 # ifdef __win32__ |
|
4488 // ALWAYS check for proper arguments, please |
|
4489 OBJ fp = __INST(handle); |
|
4490 |
|
4491 if (fp != NULL) { |
|
4492 int result; |
|
4493 u_long nonBlocking = 1; |
|
4494 SOCKET socket = SOCKET_FROM_FILE_OBJECT(fp); |
|
4495 |
|
4496 result = ioctlsocket(socket, FIONBIO, &nonBlocking); |
|
4497 if (result == SOCKET_ERROR) { |
|
4498 console_fprintf(stderr, "Win32OS [info]: ioctlsocket failed with %d\n", WSAGetLastError()); |
|
4499 RETURN(false); |
|
4500 } |
|
4501 |
|
4502 RETURN(true); |
|
4503 } |
|
4504 #endif // __win32__ |
|
4505 %}. |
|
4506 |
|
4507 self primitiveFailed. |
|
4508 |
|
4509 "Modified: / 03-03-2020 / 15:29:26 / Stefan Vogel" |
|
4510 ! ! |
4578 ! ! |
4511 |
4579 |
4512 !Socket methodsFor:'testing'! |
4580 !Socket methodsFor:'testing'! |
4513 |
4581 |
4514 isSSLSocket |
4582 isSSLSocket |