Recv fails when using python sendall in iOS project - iphone

I have a python server that is trying to send a binary file to a client on iOS but 90% of the time the file is incomplete. The receive call on the client fails after receiving about 80% of the file.
This is basically how it's setup.
Server
class ForkingTCPRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
f = open(TEST_FILE_NAME, 'rb')
file_data = f.read()
self.request.sendall(file_data)
f.close()
class ForkingTCPServer(SocketServer.ForkingMixIn, SocketServer.TCPServer):
pass
if __name__ == '__main__':
try:
server = ForkingTCPServer(('0.0.0.0', 9000), ForkingTCPRequestHandler)
except socket.error as e:
sys.exit(1)
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
sys.exit(0)
This code works outside of our iOS project (entire file is received)
int receiveFile() {
/* ... */
/* Receive file */
tempBuf = (char*) malloc(sizeof(char)*fileLen);
totalRecv = 0;
recvBytes = 0;
while (totalRecv < fileLen) {
recvBytes = recv(s, tempBuf+totalRecv, 1<<14, 0);
if (recvBytes < 0) {
free(tempBuf);
close(s);
return -1;
}
totalRecv += recvBytes;
}
close(s);
return 0;
}
int connectToServerWithHostname(char *hostname, char *port) {
/* ... */
memset(&targetAddr, 0, sizeof(targetAddr));
targetAddr.sin_family = AF_INET;
targetAddr.sin_port = htons(atoi(port));
bcopy(hostdetails->h_addr, (char *)&targetAddr.sin_addr, hostdetails->h_length);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (socket < 0) {
return -1;
}
rc = connect(sock, (struct sockaddr *)&targetAddr, sizeof(targetAddr));
if (rc < 0) {
close(sock);
return -1;
}
return sock;
}
int main(int argc, char **argv) {
assert(!receiveFile());
return 0;
}
But this equivalent code inside our iOS project fails (partial receive). Even though I'm connecting and receiving the same way as the code above.
while (totalRecv < ntohl(symProcPacket.totalDataLen)) {
recvBytes = recv(s, tempBuf+totalRecv, DEFAULT_SENDRECVSIZE, DEFAULT_SENDRECV_FLAGS);
if (recvBytes < 0) {
debug("Error, could not receive file\n");
free(tempBuf);
errorType = kSymClientErrorReceiving;
goto errorImporting;
}
totalRecv += recvBytes;
printf("Received: %d/%d\n", totalRecv, ntohl(symProcPacket.totalDataLen));
}
Any ideas on why this is failing?
Are sockets different in an iOS project or something?

Related

I receiving unknow data in my esp 8266

I need upload my own program on esp8266 and i tried to upload a program for test and i see esp reset maybe evry 200 ms and i am receivig a lot of data on usart but isn't my data in program .data is something like exception and some bytes about stack and some data about load and reset again
this is my test code
#include <ESP8266WiFi.h>
#define MAX_SRV_CLIENTS 1
#define TCP_PORT (23)
WiFiServer tcpServer(TCP_PORT);
WiFiClient tcpServerClients[MAX_SRV_CLIENTS];
IPAddress apIP(192, 168, 1, 1);
const char SSID[] = "TCPUARTBridge";
const char PASSWORD[] = "12345678";
#define SerialDebug Serial1
#define SerialGPS Serial
#ifndef min
#define min(x,y) ((x)<(y)?(x):(y))
#endif
void setup() {
SerialDebug.begin(115200);
SerialDebug.println("TCP <-> UART bridge");
WiFi.mode(WIFI_AP);
WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
WiFi.softAP(SSID, PASSWORD);
SerialGPS.begin(9600);
tcpServer.begin();
tcpServer.setNoDelay(true);
SerialDebug.print("Ready! Use 'telnet or nc ");
SerialDebug.print(WiFi.localIP());
SerialDebug.print(' ');
SerialDebug.print(TCP_PORT);
SerialDebug.println("' to connect");
}
void loop() {
uint8_t i;
char buf[1024];
int bytesAvail, bytesIn;
if (tcpServer.hasClient()) {
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (!tcpServerClients[i] || !tcpServerClients[i].connected()) {
if (tcpServerClients[i])
tcpServerClients[i].stop();
tcpServerClients[i] = tcpServer.available();
SerialDebug.print("New client: "); SerialDebug.print(i);
continue;
}
}
WiFiClient tcpServerClient = tcpServer.available();
tcpServerClient.stop();
}
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (tcpServerClients[i] && tcpServerClients[i].connected()) {
while ((bytesAvail = tcpServerClients[i].available()) > 0) {
bytesIn = tcpServerClients[i].readBytes(buf, min(sizeof(buf), bytesAvail));
if (bytesIn > 0) {
SerialGPS.write(buf, bytesIn);
delay(0);
}
}
}
}
while ((bytesAvail = SerialGPS.available()) > 0) {
bytesIn = SerialGPS.readBytes(buf, min(sizeof(buf), bytesAvail));
if (bytesIn > 0) {
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
if (tcpServerClients[i] && tcpServerClients[i].connected()) {
tcpServerClients[i].write((uint8_t*)buf, bytesIn);
delay(0);
}
}
}
}
}
Thank you for reading this

How to set SSL_connect on non blocking socket with select on linux platform

I am trying to use the select function to have non-blocking connection from a client to server.I found a tutorial with some code and tried to adapt to this:
...
sockfd = socket(AF_INET, SOCK_STREAM, 0);
err = connect(sockfd,(struct sockaddr*)&sa,sizeof(sa));
...
SSL_set_fd(pssl,sockfd);
err = SSL_connect_nonb(pssl,sockfd,60);
if(err <=0 ){
printf("SSL_connect:%s\n",ERR_error_string(SSL_get_error(pssl,err),NULL));
return -1;
}
...
The SSL_connect_nonb function is defined as bellow:
int SSL_connect_nonb(SSL*pssl,int sockfd, int nsec)
{
int flags, error;
socklen_t len;
fd_set rset, wset;
struct timeval tval;
flags = fcntl(sockfd, F_GETFL, 0);
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
int err = SSL_connect(pssl);
int err2 = SSL_get_error(pssl,err);
switch(err2) {
default:
printf("SSL_connect err=%s\n",ERR_error_string(err2,0));
return -1;
break;
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
break;
}
FD_ZERO(&rset);
FD_ZERO(&wset);
FD_SET(sockfd, &rset);
FD_SET(sockfd, &wset);
tval.tv_sec = nsec;
tval.tv_usec = 0;
if (select(sockfd+1, &rset, &wset, NULL,nsec ? &tval:NULL) == 0) {
return -1;
}
if(FD_ISSET(sockfd,&rset) || FD_ISSET(sockfd, &wset )) {
len = sizeof(error);
if(getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0){
return -1;
}
}else{
printf("sockfd not set\n");
return -1;
}
fcntl(sockfd, F_SETFL, flags);
if (error) {
return -1;
}
return 1;
}
The sockfd is correct with connect,the problem is that in SSL_connect_nonb the select function return avalue=1 (actually the condition FD_ISSET(sockfd, &wset) is successful all time),but if I use blocking method as this :
....
SSL_set_fd(pssl,sockfd);
err = SSL_connect(pssl);
if(err <=0 ){
printf("SSL_connect:%s\n",ERR_error_string(SSL_get_error(pssl,err),NULL));
return -1;
}
...
the value of err is 0 because the SSL_connect is not successful, so, how to do with SSL_connect on non blocking socket by calling select function?
SSL_connect(), aka SSL client handshake, is a complicated process, which requires several roundtrip with servers. So, when you run SSL_connect() on a non-blocking socket, it's not enough to just run it only once. When you get SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, you must retry SSL_connect() again, until it succeeded or failed with other errors.

select socket call send and recv synchronization

I am using the select call and accepting the connection from "X" no of clients.
I made duplex connection i.e. server to client and client to server.
When connection is established between 2 entities ,I am going to send
data in chunks from one entity to other.
During send I read one file in chunks and send the data in chunks.
while(file_size !=0)
{
read_bytes = read(fd, buff, sizeof(buff));
cnt_ = send(_sock_fd,buff,actually_read,0);
file_size = file_size - cnt_;
printf("total sent remaining %d : %d\n",size,actually_read);
}
while at receiver side
//First I send the header which contain size it got accepted fine but during the following send call I used "get_readable_bytes" (Using ioctl) which returns me the no of bytes arrived at socket
`while(size != 0)
{
int test_ = 0;
while(((cnt_= get_readable_bytes(_sock_fd))== 0) )//&& test_ == 0
{
cnt_= get_n_readable_bytes(_sock_fd);
printf("Total bytes recved %d\n",cnt_);
//test_ = test_ + 1;
}
while(cnt_ != 0)
{
actually_read = recv(_sock_fd, buff, sizeof(buff),0);
int _cnt = get_n_readable_bytes(_sock_fd);
printf("Total bytes recved %d\n",cnt_-_cnt);
write(_fd,buff,actually_read);
cnt_ = cnt_ - actually_read;
test_ = 0;
}
`Now the problem is
1.During this execution of receive function control automatically go to the select function and it tries to execute whole receive function again so is there any way to synchronize the sender and receivers such that when the sender complete then start receiver or as soon as sender start receiver ?
2.And how do I maintain the count of bytes sent and received.
and this is my select call
`is_read_availble = select(maxfd + 1,&read_set,NULL,NULL,&timeout)`
with timeout 10sec.
Sketch of the kind of buffer code you need. (To allow partial reads/writes, the buffers need to be persistent between calls) BTW: you really need to handle the -1 return from read() and write() because they would seriously disturb your buffer-bookkeeping. EINTR + EAGAIN/EWOULDBLOCK is very common.
struct buff {
unsigned size;
unsigned bot;
unsigned top;
char *buff;
};
struct buff bf = {0,0,0,NULL};
initialisation:
bf.buff = malloc(SOME_SIZE);
/* ... error checking omitted */
bp.size = SOME_SIZE;
bp.bot = bp.top =0;
reading:
unsigned todo;
int rc;
/* (maybe) shift the buffer down to make place */
todo = bf.top - bf.bot;
if (todo) {
memmove (bf.buff, bf.buff + bf.bot, todo);
bf.top = todo; bf.bot = 0;
}
todo = bf.size - bf.top;
if (!todo) { /* maybe throttle? ... */ return; }
rc = read (fd, bf.buff+bp.top, todo);
/* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc == 0) {...}
else {
total_read += rc;
bp.top += rc;
}
writing:
unsigned todo;
int rc;
todo = bf.top - bf.bot;
if (!todo) { /* maybe juggle fd_set ... */ return; }
rc = write (fd, bf.buff+bp.bot, todo);
/* ... error checking omitted */
if (rc == -1) switch (errno) {...}
else if (rc ==0) { ...}
else {
bp.bot += rc;
total_written += rc;
if (bp.bot == bp.top) bp.bot = bp.top =0;
}
/* ... this is the place to juggle the fd_set for writing */

C++ code to find BSSID OF associated network

Hello I've written the following code which is a part of a project. It is used to find the ESSID of the current associated network.
But it has a flaw: it also the displays the ESSID of the network with which I am not associated i.e. if I try to associate myself with a wireless n/w and if it is unsuccessful i.e. NO DHCP OFFERS ARE RECEIVED, then also it will display the that ESSID with which I have made my attempt.
Could anyone give me an ioctl call to find the BSSID of current associated wireless n/w?. In my opinion it is the only way with which I a can mark b/w associated and non associated.
CODE:-
int main (void)
{
int errno;
struct iwreq wreq;
CStdString result = "None";
int sockfd;
char * id;
char ESSID[100];
memset(&wreq, 0, sizeof(struct iwreq));
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
fprintf(stderr, "Cannot open socket \n");
fprintf(stderr, "errno = %d \n", errno);
fprintf(stderr, "Error description is : %s\n",strerror(errno));
return result ;
}
CLog::Log(LOGINFO,"Socket opened successfully");
FILE* fp = fopen("/proc/net/dev", "r");
if (!fp)
{
// TBD: Error
return result;
}
char* line = NULL;
size_t linel = 0;
int n;
char* p;
int linenum = 0;
while (getdelim(&line, &linel, '\n', fp) > 0)
{
// skip first two lines
if (linenum++ < 2)
continue;
p = line;
while (isspace(*p))
++p;
n = strcspn(p, ": \t");
p[n] = 0;
strcpy(wreq.ifr_name, p);
id = new char[IW_ESSID_MAX_SIZE+100];
wreq.u.essid.pointer = id;
wreq.u.essid.length = 100;
if ( ioctl(sockfd,SIOCGIWESSID, &wreq) == -1 ) {
continue;
}
else
{
strcpy(ESSID,id);
return ESSID;
}
free(id);
}
free(line);
fclose(fp);
return result;
}

libssh + iPhone Implementation with multiple commands execution in sequence

It seems my questions are strange and i'm not getting enough help but I'm back.
I've another strange question which needs to be solved in emergency.
I'm developing an iPhone app. which uses libssh 2 for commands execution through iPhone over remote host. It's okay and working all methods and commands if i execute them in single.
My problem is,
consider a sequence of commands,
pwd
=> o/p will be /Users/mac01
cd xyz
=> nothing as o/p
pwd
=> o/p will be /Users/mac01/xyz
So, my question is to save the last state of the command which has been executed... but what I'm getting as o/p is
/Users/mac01
after second pwd command execution, which is wrong.
So, could anyone help me out with such type of problems..? Thanks in advance.
I'm using libssh 2.0 library.
The method executing command:
char* cmd_exec(const char *commandline, const char *host, const char *username, const char *password, int port){
int sock, rc, bytecount = 0;
char *cmd_contents;
if(!he)
{
struct sockaddr_in sin;
ifdef WIN32
WSADATA wsadata;
WSAStartup(MAKEWORD(2,0), &wsadata);
endif
/* Init and Make Socket Connection */
/* Start Socket Connection */
sock = socket(AF_INET, SOCK_STREAM, 0);
ifndef WIN32
fcntl(sock, F_SETFL, 0);
endif
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
/*sin.sin_addr.s_addr = inet_addr(host);
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) { // in case connection failure
fprintf(stderr, "Internet connection is required!\n");
return "NETWORKFAILURE";
}*/
//const char *c = getIPFromHost("pepsi");
//sin.sin_addr.s_addr = inet_addr(c);
/* IP Address Calculation */
he = gethostbyname(host);
if(!he)
return "Invalid hostname";
struct in_addr **addr_list;
addr_list = (struct in_addr **)he->h_addr_list;
//for(int i = 0; addr_list[i] != NULL; i++) {
if(addr_list != NULL){
sin.sin_addr.s_addr = inet_addr(inet_ntoa(*addr_list[0]));
//printf("%s", inet_ntoa(*addr_list[0]));
if (connect(sock, (struct sockaddr*)(&sin),
sizeof(struct sockaddr_in)) != 0) { // in case connection failure
fprintf(stderr, "Internet connection is required!\n");
return "NETWORKFAILURE";
}
}
}
/* End Socket Connection */
// Initialize and create Session Instance
if(!session)
{
session = libssh2_session_init();
if ( !session )
{
fprintf( stderr, "Error initializing SSH session\n" );
return "SESSIONFAILURE";
}
/* Since we have set non-blocking, tell libssh2 we are non-blocking */
//libssh2_session_set_blocking(session, 0);
// Session starting
if (libssh2_session_startup(session, sock)) {
fprintf(stderr, "Failure establishing SSH session\n");
return "SESSIONFAILURE";
}
/* Authenticate via password */
if(strlen(password) != 0){
if ( libssh2_userauth_password( session, username, password ) )
{
fprintf( stderr, "Unable to authenticate user [%s]"
"(wrong password specified?)\n", username );
return "AUTHENTICATIONFAILURE";
}
}else{
while ((rc = libssh2_userauth_publickey_fromfile(session, username,
"/home/user/"
".ssh/id_rsa.pub",
"/home/user/"
".ssh/id_rsa",
password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "\tAuthentication by public key failed\n");
return "AUTHENTICATIONFAILURE";
}
}
//libssh2_session_set_blocking(session, 1);
}
// Open a session channel for command execution
if(!channel)
{
channel = libssh2_channel_open_session(session);
if (!channel) {
fprintf(stderr, "Unable to open a session\n");
return "SESSIONFAILURE";
}
// Execute a command through channel
while( (rc = libssh2_channel_shell(channel)) ==
//while( (rc = libssh2_channel_exec(channel, commandline)) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
if( rc != 0 ) // if command execution failed
{
fprintf(stderr,"Error\n");
return "CMDFAILURE";
}
}
//libssh2_channel_write(channel,commandline,strlen(commandline));
do {
/* write the same data over and over, until error or completion */
rc = libssh2_channel_write(channel, commandline, sizeof(commandline));
if (rc < 0) {
fprintf(stderr, "ERROR %d\n", rc);
}
} while (rc == 0);
while (libssh2_channel_send_eof(channel) == LIBSSH2_ERROR_EAGAIN);
/* read channel output */
/* Start channel read */
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
// char *tcontents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
if( rc > 0 )
{
int i;
bytecount += rc;
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
if(cmd_contents){
free(cmd_contents);
}
cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
strcpy(cmd_contents, buffer);
fprintf(stderr, "\n");
}
else {
//fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
}
}
while( rc > 0 );
/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
else
break;
}
/* End channel read */
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN );
/* closing channel */
int exitcode = 127;
// while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN );
if( rc == 0 )
{
exitcode = libssh2_channel_get_exit_status( channel );
}
//
libssh2_channel_free(channel); // freeup memory
channel = NULL;
/*
libssh2_session_disconnect( session, "" ); // closing session
libssh2_session_free( session ); // free up memory
close( sock ); // closing socket
*/
return cmd_contents;
}
Try this maybe it works... i havent tried it but you can get enough idea and may be the proper solution
libssh2_session_set_blocking(session, 0);
char buffer[0x4000]; rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
  if(cmd_contents)
{
free(cmd_contents);
 }
  buffer[i] = '\0';
  cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
  strcpy(cmd_contents, buffer);
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}
hAPPY cODING...
libssh2_session_set_blocking(session, 0);
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
if(cmd_contents){
free(cmd_contents);
}
buffer[i] = '\0';
cmd_contents = (char*)malloc(sizeof(buffer) + sizeof(cmd_contents));
strcpy(cmd_contents, buffer);
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(sock, session);
}