2424#include " llamafile/server/server.h"
2525#include " llamafile/server/time.h"
2626#include " llamafile/server/tokenbucket.h"
27+ #include " llamafile/server/utils.h"
2728#include " llamafile/server/worker.h"
2829#include " llamafile/string.h"
2930#include " llamafile/threadlocal.h"
@@ -478,7 +479,7 @@ Client::send_response_chunk(const std::string_view content)
478479
479480 // perform send system call
480481 ssize_t sent;
481- if ((sent = writev (fd_, iov, 3 )) != bytes) {
482+ if ((sent = safe_writev (fd_, iov, 3 )) != bytes) {
482483 if (sent == -1 && errno != EAGAIN && errno != ECONNRESET)
483484 SLOG (" writev failed %m" );
484485 close_connection_ = true ;
@@ -504,15 +505,34 @@ Client::send_response_finish()
504505 return send (" 0\r\n\r\n " );
505506}
506507
507- // writes raw data to socket
508+ // writes any old data to socket
509+ //
510+ // unlike send() this won't fail if binary content is detected.
511+ bool
512+ Client::send_binary (const void * p, size_t n)
513+ {
514+ ssize_t sent;
515+ if ((sent = write (fd_, p, n)) != n) {
516+ if (sent == -1 && errno != EAGAIN && errno != ECONNRESET)
517+ SLOG (" write failed %m" );
518+ close_connection_ = true ;
519+ return false ;
520+ }
521+ return true ;
522+ }
523+
524+ // writes non-binary data to socket
508525//
509526// consider using the higher level methods like send_error(),
510527// send_response(), send_response_start(), etc.
511528bool
512529Client::send (const std::string_view s)
513530{
531+ iovec iov[1 ];
514532 ssize_t sent;
515- if ((sent = write (fd_, s.data (), s.size ())) != s.size ()) {
533+ iov[0 ].iov_base = (void *)s.data ();
534+ iov[0 ].iov_len = s.size ();
535+ if ((sent = safe_writev (fd_, iov, 1 )) != s.size ()) {
516536 if (sent == -1 && errno != EAGAIN && errno != ECONNRESET)
517537 SLOG (" write failed %m" );
518538 close_connection_ = true ;
@@ -521,7 +541,7 @@ Client::send(const std::string_view s)
521541 return true ;
522542}
523543
524- // writes two pieces of raw data to socket in single system call
544+ // writes two pieces of non-binary data to socket in single system call
525545//
526546// consider using the higher level methods like send_error(),
527547// send_response(), send_response_start(), etc.
@@ -534,7 +554,7 @@ Client::send2(const std::string_view s1, const std::string_view s2)
534554 iov[0 ].iov_len = s1.size ();
535555 iov[1 ].iov_base = (void *)s2.data ();
536556 iov[1 ].iov_len = s2.size ();
537- if ((sent = writev (fd_, iov, 2 )) != s1.size () + s2.size ()) {
557+ if ((sent = safe_writev (fd_, iov, 2 )) != s1.size () + s2.size ()) {
538558 if (sent == -1 && errno != EAGAIN && errno != ECONNRESET)
539559 SLOG (" writev failed %m" );
540560 close_connection_ = true ;
@@ -755,7 +775,7 @@ Client::dispatcher()
755775 close_connection_ = true ;
756776 return false ;
757777 }
758- if (!send ( std::string_view ( buf, chunk) )) {
778+ if (!send_binary ( buf, chunk)) {
759779 close_connection_ = true ;
760780 return false ;
761781 }
0 commit comments