How to catch exceptions from gsoap? - iphone

I'm currently building an iphone app based on gsoap for the communication. I'm trying to manage connection problems and I can't find any specific return statement when the device is not connected to host.
Is there a way to get some kind of exceptions when running gsoap send or reicv methods?
Thanks for help,
Romain

From http://www.cs.fsu.edu/~engelen/soap.html there is even a useful function for printing a human readable error message:
#include "soapcalcProxy.h" // get proxy
#include "calc.nsmap" // get namespace bindings
int main()
{
calc s;
double r;
if (s.ns2__add(1.0, 2.0, r) == SOAP_OK)
std::cout << r << std::endl;
else
soap_print_fault(s.soap, stderr);
return 0;
}

Related

Can one reliably connect a TCP socket to itself?

I am wondering whether it is possible to reliably connect a TCP socket to itself -- that is, to get just one socket where whatever you send() on you receive back through recv(). I saw that this can happen (e.g., here, here, and here), but none of these posts explain how to do this programmatically and reliably (i.e., this is usually touted as a curiosity, rather than a feature one would use deliberately). I'm interested in a solution for Windows, Mac, and Linux.
Just for completeness, please let me explain why I'm interested in this. I'm writing a cloud-based application where servers can send messages to other servers, including themselves. Each server uses one socket to talk to other servers, and so, to unify the code and make certain threading issues simpler, it would be good if the server could talk to itself using just one socket as well.
EDIT: #Rufflewind suggested connecting to the loopback adapter. I tried that using the code below, both with and without the call to listen. In all cases, however, I got an error (either "Invalid argument" or "Operation not supported"). What am I doing wrong?
#include <iostream>
#include <netinet/tcp.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void die(const char* const message) {
perror(message);
exit(0);
}
#define CHECK(operation,message) \
if ((operation) != 0) \
die(message)
int main(int argc, char* argv[]) {
sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(40000);
inet_aton("127.0.0.1", &local.sin_addr);
int sck = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
CHECK(bind(sck, (struct sockaddr *)&local, sizeof(local)), "Error while binding the socket to an address");
// CHECK(listen(sck, 1), "Error while listening.");
CHECK(connect(sck, (struct sockaddr *)&local, sizeof(local)), "Error while connecting the socket to self");
std::cout << "Succeeded in connecting sockets!" << std::endl;
const char* message = "ABCDEFGH";
const size_t messageLength = ::strlen(message) + 1;
const char* currentSend = message;
ssize_t leftToSend = messageLength;
while (leftToSend != 0) {
const ssize_t sent = send(sck, currentSend, leftToSend, 0);
if (sent == -1)
die("Can't send.");
currentSend += sent;
leftToSend -= sent;
}
std::cout << "Sent the message!" << std::endl;
char buffer[256];
char* currentRead = buffer;
size_t leftToRead = messageLength;
while (leftToRead != 0) {
const ssize_t read = recv(sck, currentRead, leftToRead, 0);
if (read == -1)
die("Can't read.");
currentRead += read;
leftToRead -= read;
}
std::cout << "Received message: " << buffer << std::endl;
return 0;
}
The most straightforward approach would be to bind to the loopback adapter. Just listen to 127.0.0.1 on some arbitrary port and the connect to that.
The problem with this approach is that the port is global on the machine, so that means other programs can connect to it too, and if you have multiple programs you might run into conflicts or conceivably exhaust all the possible ports.
Another approach is to use Unix domain sockets, but this is not supported on Windows.

Why isn't opus_encode_float output acceptable input to decodeAudioData?

Web browser support for the opus audio codec is normally utilized by delivering an entire opus-encoded file to the browser, and this is known to work for firefox and chrome, for example. My scenario is different in that I stream opus packets from server to browser.
On a linux server I encode audio with opus_encode_float. It is delivered to a web browser client via WebSocket. In the browser I use the Web Audio API's decodeAudioData to try to decode that same data. It fails in firefox and chrome with a null exception.
Seems to me this should work, if not last year then Real Soon Now. Can anyone either tell me the status of the opus implementations in the browsers, or tell me what I'm doing wrong? Thanks in advance.
// .h
#define OPUS_FRAME_SIZE 1920
#define MAX_FRAME_SIZE 6*OPUS_FRAME_SIZE
#define MAX_PACKET_SIZE (4*OPUS_FRAME_SIZE)
class OpusEncoder; // forward declaration as we don't want to include opus.h here
class xxx {
OpusEncoder *encoder; // Holds the state of the opus encoder
unsigned char opusOutBuf[MAX_PACKET_SIZE];
}
// .cpp
#include <opus.h>
#define CHANNELS 2
#define SAMPLE_RATE 48000
#define APPLICATION OPUS_APPLICATION_AUDIO
#define BITRATE 64000
// one time code
// Create a new encoder state
int err;
encoder = opus_encoder_create(SAMPLE_RATE, CHANNELS, APPLICATION, &err);
if (err<0)
{
LogIt(prError) << "Failed to create an Opus encoder: " << opus_strerror(err);
return;
}
err = opus_encoder_ctl(encoder, OPUS_SET_BITRATE(BITRATE));
if (err<0)
{
LogIt(prError) << "Opus failed to set bitrate: " << opus_strerror(err);
return ;
}
// per packet code
int nbBytes = opus_encode_float(encoder, IncomingAudio, OPUS_FRAME_SIZE, opusOutBuf, MAX_PACKET_SIZE);
if (nbBytes < 0)
{
LogIt(prError) << "Opus encode failed: " << opus_strerror(nbBytes);
return;
}
// Client side javascript
// OpusEncodedArrayBuffer is an unmodified binary packet that
// arrived via websocket onmessage(evt); it is evt.data
window.context.decodeAudioData(OpusEncodedArrayBuffer, function(buffer) { // use "classic" callback
if (buffer) { // I would LIKE to arrive here, but so far no joy.
// ...
}
},
function(e){
if (e) {
tell("error in decodeAudioData: " + e) // I haven't seen this case yet
} else { // This ALWAYS happens, using latest firefox or chrome
tell("error in decodeAudioData"); // webaudio api spec says decodeAudioData does not return an object error
}
});
Chrome's decodeAudioData function does not support opus. There's an open bug on this issue.

WSAConnect returns WSAEINVAL on WindowsXP

I use sockets in non-blocking mode, and sometimes WSAConnect function returns WSAEINVAL error.
I investigate a problem and found, that it occurs if there is no pause (or it is very small ) between
WSAConnect function calls.
Does anyone know how to avoid this situation?
Below you can found source code, that reproduce the problem. If I increase value of parameter in Sleep function to 50 or great - problem dissapear.
P.S. This problem reproduces only on Windows XP, on Win7 it works well.
#undef UNICODE
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <iostream>
#include <windows.h>
#pragma comment(lib, "Ws2_32.lib")
static int getError(SOCKET sock)
{
DWORD error = WSAGetLastError();
return error;
}
void main()
{
SOCKET sock;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
fprintf(stderr, "Socket Initialization Error. Program aborted\n");
return;
}
for (int i = 0; i < 1000; ++i) {
struct addrinfo hints;
struct addrinfo *res = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
if (0 != getaddrinfo("172.20.1.59", "8091", &hints, &res)) {
fprintf(stderr, "GetAddrInfo Error. Program aborted\n");
closesocket(sock);
WSACleanup();
return;
}
struct addrinfo *ptr = 0;
for (ptr=res; ptr != NULL ;ptr=ptr->ai_next) {
sock = WSASocket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol, NULL, 0, NULL); //
if (sock == INVALID_SOCKET)
int err = getError(sock);
else {
u_long noblock = 1;
if (ioctlsocket(sock, FIONBIO, &noblock) == SOCKET_ERROR) {
int err = getError(sock);
closesocket(sock);
sock = INVALID_SOCKET;
}
break;
}
}
int ret;
do {
ret = WSAConnect(sock, ptr->ai_addr, (int)ptr->ai_addrlen, NULL, NULL, NULL, NULL);
if (ret == SOCKET_ERROR) {
int error = getError(sock);
if (error == WSAEWOULDBLOCK) {
Sleep(5);
continue;
}
else if (error == WSAEISCONN) {
fprintf(stderr, "+");
closesocket(sock);
sock = SOCKET_ERROR;
break;
}
else if (error == 10037) {
fprintf(stderr, "-");
closesocket(sock);
sock = SOCKET_ERROR;
break;
}
else {
fprintf(stderr, "Connect Error. [%d]\n", error);
closesocket(sock);
sock = SOCKET_ERROR;
break;
}
}
else {
int one = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one));
fprintf(stderr, "OK\n");
break;
}
}
while (1);
}
std::cout<<"end";
char ch;
std::cin >> ch;
}
You've got a whole basketful of errors and questionable design and coding decisions here. I'm going to have to break them up into two groups:
Outright Errors
I expect if you fix all of the items in this section, your symptom will disappear, but I wouldn't want to speculate about which one is the critical fix:
Calling connect() in a loop on a single socket is simply wrong.
If you mean to establish a connection, drop it, and reestablish it 1000 times, you need to call closesocket() at the end of each loop, then call socket() again to get a fresh socket. You can't keep re-connecting the same socket. Think of it like a power plug: if you want to plug it in twice, you have to unplug (closesocket()) between times.
If instead you mean to establish 1000 simultaneous connections, you need to allocate a new socket with socket() on each iteration, connect() it, then go back around again to get another socket. It's basically the same loop as for the previous case, except without the closesocket() call.
Beware that since XP is a client version of Windows, it's not optimized for handling thousands of simultaneous sockets.
Calling connect() again is not the correct response to WSAEWOULDBLOCK:
if (error == WSAEWOULDBLOCK) {
Sleep(5);
continue; /// WRONG!
}
That continue code effectively commits the same error as above, but worse, if you only fix the previous error and leave this, this usage will then make your code start leaking sockets.
WSAEWOULDBLOCK is not an error. All it means after a connect() on a nonblcoking socket is that the connection didn't get established immediately. The stack will notify your program when it does.
You get that notification by calling one of select(), WSAEventSelect(), or WSAAsyncSelect(). If you use select(), the socket will be marked writable when the connection gets established. With the other two, you will get an FD_CONNECT event when the connection gets established.
Which of these three APIs to call depends on why you want nonblocking sockets in the first place, and what the rest of the program will look like. What I see so far doesn't need nonblocking sockets at all, but I suppose you have some future plan that will inform your decision. I've written an article, Which I/O Strategy Should I Use (part of the Winsock Programmers' FAQ) which will help you decide which of these options to use; it may instead guide you to another option entirely.
You shouldn't use AI_PASSIVE and connect() on the same socket. Your use of AI_PASSIVE with getaddrinfo() tells the stack you intend to use this socket to accept incoming connections. Then you go and use that socket to make an outgoing connection.
You've basically lied to the stack here. Computers find ways to get revenge when you lie to them.
Sleep() is never the right way to fix problems with Winsock. There are built-in delays within the stack that your program can see, such as TIME_WAIT and the Nagle algorithm, but Sleep() is not the right way to cope with these, either.
Questionable Coding/Design Decisions
This section is for things I don't expect to make your symptom go away, but you should consider fixing them anyway:
The main reason to use getaddrinfo() — as opposed to older, simpler functions like inet_addr() — is if you have to support IPv6. That kind of conflicts with your wish to support XP, since XP's IPv6 stack wasn't nearly as heavily tested during the time XP was the current version of Windows as its IPv4 stack. I would expect XP's IPv6 stack to still have bugs as a result, even if you've got all the patches installed.
If you don't really need IPv6 support, doing it the old way might make your symptoms disappear. You might end up needing an IPv4-only build for XP.
This code:
for (int i = 0; i < 1000; ++i) {
// ...
if (0 != getaddrinfo("172.20.1.59", "8091", &hints, &res)) {
...is inefficient. There is no reason you need to keep reinitializing res on each loop.
Even if there is some reason I'm not seeing, you're leaking memory by not calling freeaddrinfo() on res.
You should initialize this data structure once before you enter the loop, then reuse it on each iteration.
else if (error == 10037) {
Why aren't you using WSAEALREADY here?
You don't need to use WSAConnect() here. You're using the 3-argument subset that Winsock shares with BSD sockets. You might as well use connect() here instead.
There's no sense making your code any more complex than it has to be.
Why aren't you using a switch statement for this?
if (error == WSAEWOULDBLOCK) {
// ...
}
else if (error == WSAEISCONN) {
// ...
}
// etc.
You shouldn't disable the Nagle algorithm:
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ...);

How to make a G-WAN servlet close its connection silently without sending any reply

How to have gwan send no reply to some requests, i.e. make a servlet closed silently without building and sending a reply?
It is useful to reduce the out-going bandwidth from the server side.
For collecting data only, there's no need to respond anything to the client.
You can also close the connection from the servlet by doing something like (untested):
#include <sys/socket.h>
char buf[1024];
int s = (int)get_env(argv, CLIENT_SOCKET);
shutdown(s, SHUT_WR);
while(read(s, buf, sizeof(buf)) > 0);
close(s);
return 500;
Then return something like 500 like above so you don't have to build a reply.
You can do that with a gwan connection handler.
I think this is the event that you need to catch on the handler. Since you want the servlet to run then close the connection after.
HDL_BEFORE_WRITE, // after a reply was built, but before it is sent
Here is a sample code for the connection handler. You still need to add your filter. This code will close all requests after the reply was built.
int init(int argc, char *argv[])
{
u32 *states = (u32*)get_env(argv, US_HANDLER_STATES);
*states = (1 << HDL_BEFORE_WRITE)
}
int main(int argc, char *argv[])
{
long state = (long)argv[0];
if(state == HDL_BEFORE_WRITE)
{
return 0; // Close connection
}
return(255); // continue G-WAN's default execution path
}

Qt and threaded local server , why is the whole UI stuck?

Here's a minimal test case , I tried to start a local domain server , with QThread , so the UI shouldn't stuck. But when it's starting , i saw Listening output from qDebug() , but the widgets added from form editor totally disappeared , everything went slow (e.g resizing the window) , if i remove thread.start() , the UI shows up and functions well.
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect (&thread , SIGNAL(started()) , SLOT(setupServer()));
thread.start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setupServer()
{
struct sockaddr_un address;
int socket_fd, connection_fd;
socklen_t address_length;
// create socket .. and create socket file ..
// bind ...
// listen ..
qDebug() << "Listening ..";
while((connection_fd = ::accept(socket_fd,
(struct sockaddr *) &address,
&address_length)) > -1)
{
qDebug() << "Got an connection.";
::close (connection_fd);
}
// close socket and remove the socket file
}
The accept(2) syscall is by default blocking. You should take advantage of the multiplexing syscall poll(2) or select(2) used by the QApplication's exec event loop.
See this question and use the QtNetwork module.
First of all, your setupServer is always called in gui thread. Deliver your own QThread based class and reimplement run method. Put your "setupServer" code inside