phpbar.de logo

Mailinglisten-Archive

[php] C extension für php unter linux: unix domain sockets zum versenden von descriptoren

[php] C extension für php unter linux: unix domain sockets zum versenden von descriptoren

Jedenastik, Günther guenther.jedenastik at maxolution.at
Mon Jan 9 12:45:17 CET 2006


Ich habe folgenden code:

/* {{{ PHP_MCLS_RECVSOCK
*/
PHP_FUNCTION(my_recvfd)
{
 php_stream *ostream=NULL;
 php_stream *istream=NULL;
 int isock=-1,osock=-1;
 char buff[1024]={0};

 zval *zstream=NULL;

 if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream)){
  RETURN_FALSE;
 }

 php_stream_from_zval(istream, &zstream);

 if(php_stream_can_cast(istream,PHP_STREAM_AS_SOCKET) != SUCCESS){
  RETURN_FALSE;
 }

 if(php_stream_cast(istream,PHP_STREAM_AS_SOCKETD,(void*)&isock,REPORT_ERRORS) == FAILURE){
  RETURN_FALSE;
 }

 struct msghdr msg;
 char cmsgbuf[4096]={0};
 char databuf[4096]={0};
 struct cmsghdr *cmsg;
 struct iovec iovec;
 int r;
 int datalen=0;
 iovec.iov_base = databuf;
 iovec.iov_len = sizeof(databuf);
 msg.msg_name = NULL;
 msg.msg_namelen = 0;
 msg.msg_iov = &iovec;
 msg.msg_iovlen = 1;
 msg.msg_control = cmsgbuf;
 msg.msg_controllen = sizeof(cmsgbuf);
 msg.msg_flags = MSG_WAITALL;
 r = recvmsg(isock, &msg, 0);

 if(r>0){
  if(!(msg.msg_flags&(MSG_TRUNC | MSG_CTRUNC))){
   datalen=r;
   for(cmsg=CMSG_FIRSTHDR(&msg);cmsg!=NULL;cmsg=CMSG_NXTHDR(&msg,cmsg)){
    if(cmsg->cmsg_level!=SOL_SOCKET){
     RETURN_FALSE;
    }

    switch(cmsg->cmsg_type){
     case SCM_RIGHTS:{
                      if(cmsg->cmsg_len!=CMSG_LEN(sizeof(isock))){
                       RETURN_FALSE;
                      }
                      int *tmp=NULL;
                      tmp=&osock;
                      *tmp=*(typeof(&isock))CMSG_DATA(cmsg);
                      break;
                     }
     default:{
                   RETURN_FALSE;
             }
    }
    if(osock==-1){
     RETURN_FALSE;
    }
   }
  }
  else{
   RETURN_FALSE;
  }
 }
 else{
  RETURN_FALSE;
 }

 if(osock==-1){
  RETURN_FALSE;
 }

 ostream=php_stream_sock_open_from_socket(osock,0);

 php_stream_to_zval(ostream, return_value);
}
/* }}} */

Der code selbst dürfte wunderbar funktionieren, dennoch krieg ich von
	PHPAPI int _php_stream_cast(php_stream *stream, int castas, void
In
	/php-src/main/streams/cast.c
Eine warning:
"4 bytes of buffered data lost during stream conversion!"

Die warning krieg ich 2mal weil ich die funktion 2 mal aufrufe

Was mache ich eigentlich?
Ich verwende unix domain sockets zum versenden von bereits geöffneten sockets
d.h. ich möchte von prozess A eine socket verbindung zu meinem php script (also prozess B) senden

warum krieg ich die warning?
In cast.c steht folgendes:

        if ((stream->writepos - stream->readpos) > 0 &&
                        stream->fclose_stdiocast != PHP_STREAM_FCLOSE_FOPENCOOKIE &&
                        (flags & PHP_STREAM_CAST_INTERNAL) == 0) {
                /* the data we have buffered will be lost to the third party library that
                 * will be accessing the stream.  Emit a warning so that the end-user will
                 * know that they should try something else */

                php_error_docref(NULL TSRMLS_CC, E_WARNING,
                                "%ld bytes of buffered data lost during stream conversion!",
                                (long)(stream->writepos - stream->readpos));
        }

d.h. es wird scheinbar geprüft ob schon etwas in dem socket drinnen steht und wenn ja eine warning zurückgegeben

frage:
Wie kann ich die warning verhindern, denn für mein problem, ist die warning 
1. unnötig
2. nicht korrekt, denn natürlich stehen ein paar bytes im socket damit ich den neuen socket empfangen kann

Oder kennt jemand einen workaround?
Möglicherweiße sind andere flags hilfreich? Aber welche?

thx at ll

php::bar PHP Wiki   -   Listenarchive