I'm totally new in developing, so I understand that my code can be absolutely incorrect. But I have a problem with connecting the second client in the server. I've found bug with accept function. When I try to connect the second client my program stops work, server waiting to data from second client, but I can't send data. I've tried to use WSAGetLastError(), but it returns 0. Please, help me.
It's my server:
# include <iostream>
# include <WinSock2.h>
# pragma comment(lib,"ws2_32.lib")
class tictac {
char garr[10];
public:
tictac() {garr[0]='0'; for(int i=0; i<10;++i){garr[i]=garr[0]+i;}}
void move(int turn, char field_change) {
garr[turn]=field_change;
}
char chack(int chack) {
if(garr[chack]=='O'||garr[chack]=='X') {
return 'B';
} else {
return 'U';
}
}
} ;
class play {
tictac OurGame;
SOCKADDR_IN playerTurn1;
SOCKADDR_IN playerTurn2;
SOCKET playerSock1;
SOCKET playerSock2;
public:
int play1(){
WSAData game_one;
if((WSAStartup(MAKEWORD(2,2), &game_one))!=0) {
std::cout<<"Filed to init socket library. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 1;
}
SOCKET serverSocket = socket(2,1,6);
if(serverSocket==INVALID_SOCKET) {
std::cout<<"Fail to create socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 2;
}
SOCKADDR_IN serverGame;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=INADDR_ANY;
if(bind(serverSocket, (sockaddr*)&serverGame,sizeof(serverGame))!=0) {
std::cout<<"Fail to bind socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 3;
}
listen(serverSocket, 5);
///////////////////////////////////////////////////////////////////////////////////////////////////
playerTurn1;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=inet_addr("127.0.0.1");
//////////////////////////////////////////////////////////////////////////////////////////////////
int size1=sizeof(playerTurn1);
playerSock1 = accept(serverSocket, (sockaddr*)& playerTurn1, &size1); // Socket of first player
if(playerSock1==INVALID_SOCKET) {
std::cout<<"Failed accept with player 1. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 4;
}
char msg[2]="y";
int turn;
while(msg[0]!='Y'){
// ================================= ******* ******* ****** Turn of player one
recv(playerSock1, msg, 2, 0);
std::cout<<msg[0]<<std::endl;
turn=atoi(&msg[0]);
if(turn==0||OurGame.chack(turn)=='B') {
msg[0]='N';
send(playerSock1, msg, 2, 0);
std::cout<<"fail"<<std::endl;
} else {
msg[0]='Y';
OurGame.move(turn, 'X');
send(playerSock1, msg, 2, 0);
}
}
if(closesocket(serverSocket)==SOCKET_ERROR) {std::cout<<"ERROR With closing server socket !"<<std::endl; }
if(closesocket(playerSock1)==SOCKET_ERROR) { std::cout<<"ERROR With closing player's socket !"<<std::endl;}
system ("pause");
WSACleanup();
}
int play2() {
WSAData game_two;
if((WSAStartup(MAKEWORD(2,2), &game_two))!=0) {
std::cout<<"Filed to init socket library. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 1;
}
SOCKET serverSocket = socket(2,1,6);
if(serverSocket==INVALID_SOCKET) {
std::cout<<"Fail to create socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 2;
}
SOCKADDR_IN serverGame;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=INADDR_ANY;
if(bind(serverSocket, (sockaddr*)&serverGame,sizeof(serverGame))!=0) {
std::cout<<"Fail to bind socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 3;
}
listen(serverSocket, 5);
///////////////////////////////////////////////////////////////////////////////////////////////////
playerTurn2;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=inet_addr("127.0.0.1");
//////////////////////////////////////////////////////////////////////////////////////////////////
int size2=sizeof(playerTurn2);
playerSock1 = accept(serverSocket, (sockaddr*)& playerTurn1, &size2); // Socket of second player
std::cout<<"I beg of you, say me something!"<<std::endl; system ("pause");
if(playerSock1==INVALID_SOCKET) {
std::cout<<"Failed accept with player 1. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 4;
}
char msg[2]="y";
int turn;
while(msg[0]!='Y'){
// ================================= ******* ******* ****** Turn of player one
recv(playerSock1, msg, 2, 0);
std::cout<<msg[0]<<std::endl;
turn=atoi(&msg[0]);
if(turn==0||OurGame.chack(turn)=='B') {
msg[0]='N';
send(playerSock1, msg, 2, 0);
std::cout<<"fail"<<std::endl;
} else {
msg[0]='Y';
OurGame.move(turn, 'X');
send(playerSock1, msg, 2, 0);
}
}
if(closesocket(serverSocket)==SOCKET_ERROR) {std::cout<<"ERROR With closing server socket !"<<std::endl; }
if(closesocket(playerSock1)==SOCKET_ERROR) { std::cout<<"ERROR With closing player's socket !"<<std::endl;}
system ("pause");
WSACleanup();
}
} ;
int main() {
play PlayGame;
int queue=0;
while(true){
if(queue%2==0){
std::cout<<"first player"<<std::endl;
PlayGame.play1();
++queue;
} else {
std::cout<<"Second player"<<std::endl;
PlayGame.play2();
++queue;
}
}
}
It's my first client:
# include <iostream>
# include <WinSock2.h>
# pragma comment(lib,"ws2_32.lib")
class Game {
char cell[9];
public:
Game() {cell[0]='1'; for(int i=0; i<9; ++i){cell[i]=cell[0]+i;}}
void board() { // ==================== ======================= * * * This method just prints start game board
char table[3][3];
int index=0;
std::cout<<" GAME BOARD"<<std::endl<<std::endl;
std::cout<<"Player 1 you use X"<<std::endl;
std::cout<<"Player 2 you use O"<<std::endl<<std::endl;
for(int i=0; i<3; ++i) {
std::cout<<" ";
for(int j=0; j<3; ++j) {
table[i][j]=cell[index];
if(index!=2&&index!=5&&index!=8){
std::cout<<table[i][j]<<" | ";
} else {
std::cout<<table[i][j];
}
++index;
}
std::cout<<std::endl;
if(index<9){
std::cout<<" "<<"-----------"<<std::endl;
}
}
std::cout<<std::endl<<std::endl;
}
void change(int t) { // ========= ========= * * * This method helps user to fill field on the game board
system ("cls");
Game::cell;
cell[t-1]='X';
Game::board();
}
} ;
int main() {
// ================================================------------------_________ * * * Client
WSAData game;
if((WSAStartup(MAKEWORD(2,2), &game))!=0) {
std::cout<<"Filed to init socket library. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 1;
}
SOCKET serverSocket = socket(2,1,6);
if(serverSocket==INVALID_SOCKET) {
std::cout<<"Fail to create socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 2;
}
SOCKADDR_IN serverGame;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=inet_addr("127.0.0.1");
if(connect(serverSocket, (sockaddr*)&serverGame,sizeof(serverGame))!=0) {
std::cout<<"Fail to connect socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 3;
}
// ===========================----------------------------------- ********** Try to send data !!!!!!!!!!!
// =========================== * * * Turn of player one
Game tic_tac_toe;
tic_tac_toe.board();
char msg[2]="n";
char field[1]; // ``````````````````````````````````````This variable exists to change field on the board
if(serverSocket==INVALID_SOCKET) {std::cout<<"Problem is here"<<std::endl; system ("pause");}
while(serverSocket!=INVALID_SOCKET){
std::cout<<"Chose field (enter number of field) : ";
start:
std::cin.getline(field, 3);
msg[0]=field[0]; std::cout<<atoi(&field[0])<<" "<<msg[0]<<std::endl;
send(serverSocket, msg, 2, 0);
recv(serverSocket, msg, 2, 0);
if(msg[0]=='N') {
std::cout<<"Error (!). Invalid input (!). Chose field again : ";
goto start;
} else if(msg[0]=='Y') {
system ("cls");
tic_tac_toe.change(atoi(&field[0]));
}
closesocket(serverSocket);
WSACleanup();
}
}
It's my second client
# include <iostream>
# include <WinSock2.h>
# pragma comment(lib,"ws2_32.lib")
class Game {
char cell[9];
public:
Game() {cell[0]='1'; for(int i=0; i<9; ++i){cell[i]=cell[0]+i;}}
void board() { // ==================== ======================= * * * This method just prints start game board
char table[3][3];
int index=0;
std::cout<<" GAME BOARD"<<std::endl<<std::endl;
std::cout<<"Player 1 you use X"<<std::endl;
std::cout<<"Player 2 you use O"<<std::endl<<std::endl;
for(int i=0; i<3; ++i) {
std::cout<<" ";
for(int j=0; j<3; ++j) {
table[i][j]=cell[index];
if(index!=2&&index!=5&&index!=8){
std::cout<<table[i][j]<<" | ";
} else {
std::cout<<table[i][j];
}
++index;
}
std::cout<<std::endl;
if(index<9){
std::cout<<" "<<"-----------"<<std::endl;
}
}
std::cout<<std::endl<<std::endl;
}
void change(int t) { // ========= ========= * * * This method helps user to fill field on the game board
system ("cls");
Game::cell;
cell[t-1]='O';
Game::board();
}
} ;
int main() {
// ================================================------------------_________ * * * Client
WSAData game;
if((WSAStartup(MAKEWORD(2,2), &game))!=0) {
std::cout<<"Filed to init socket library. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 1;
}
SOCKET serverSocket = socket(2,1,6);
if(serverSocket==INVALID_SOCKET) {
std::cout<<"Fail to create socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 2;
}
SOCKADDR_IN serverGame;
serverGame.sin_family=2;
serverGame.sin_port=htons(4324);
serverGame.sin_addr.s_addr=inet_addr("127.0.0.1");
if(connect(serverSocket, (sockaddr*)&serverGame,sizeof(serverGame))!=0) {
std::cout<<"Fail to connect socket. Code : "<<WSAGetLastError()<<std::endl;
system ("pause");
return 3;
}
// ===========================----------------------------------- ********** Try to send data !!!!!!!!!!!
// =========================== * * * Turn of player one
Game tic_tac_toe;
tic_tac_toe.board();
char msg[2]="n";
char field[2]; // ``````````````````````````````````````This variable exists to change field on the board
if(serverSocket==INVALID_SOCKET) {std::cout<<"Problem is here"<<std::endl;}
while(serverSocket!=INVALID_SOCKET){
std::cout<<"Chose field (enter number of field) : ";
while(msg[0]!='Y'){
std::cin.getline(field, 2);
msg[0]=field[0]; std::cout<<msg[0]; std::cin.get();
send(serverSocket, msg, 2, 0);
recv(serverSocket, msg, 2, 0);
if(msg[0]=='N') {
std::cout<<"Error (!). Invalid input (!). Chose field again : ";
} else if(msg[0]=='Y') {
system ("cls");
tic_tac_toe.change(atoi(&field[0]));
}
}
}
}
I've found my problem. I didn't understand how this connection works.
Related
I'm having an issue with my code, I'm trying to create an HTTP server using C++ 98 on MacOS, and I'm expecting the block of read to be executed before the write one, but the opposite is happening and I don't know why.
So I'm expecting to read first the request, then send a response. but the opposite is happening here,
this my code:
/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Server::Server(int addr, int port)
{
this->sock.create_socket(AF_INET, SOCK_STREAM, 0);
this->sock.bind_socket(addr, port);
this->sock.listen_socket(__MAX_BACKLOG__);
}
webserv::Server::~Server() {}
/************************ MEMBER FUNCTION ************************/
void webserv::Server::lunch()
{
this->kq.create_event(this->sock.getSocket(), EVFILT_READ);
while (1)
this->_lunch_worker();
}
void webserv::Server::_lunch_worker(void)
{
int ev_count = this->kq.get_event();
static const char* index_html = "HTTP/1.0 200 OK\r\n" \
"Content-Length: 86\r\n\r\n" \
"<!DOCTYPE html>" \
"<html><head>Hello, world!</head><body><h1>cdn-ish...</h1></body></html>\r\n";
char buf[10000];
for (int i = 0; i < ev_count; i++) {
int fd = this->kq.get_fd(i);
if (fd < 0) continue;
if (fd == this->sock.getSocket()) {
int clientaddr_size = sizeof(this->sock.getAddress());
int clientfd = this->sock.accept_socket();
if (clientfd < 0) {
perror("accept");
close(fd);
return ;
}
this->kq.create_event(clientfd, EVFILT_READ);
if (fcntl(clientfd, F_SETFL, O_NONBLOCK) < 0) {
perror("fcntl");
close(clientfd);
close(fd);
}
this->kq.create_event(clientfd, EVFILT_WRITE, EV_ADD | EV_ONESHOT);
// EXPECTING THIS BLOCK TO BE CHECKED/EXECUTED FIRST
// BUT INSTEAD THE NEXT BLOCK (WRITE BLOCK) IS EXECUTED FIRST
// THEN IN THE SECOND ITERATION THE READ BLOCK IS BEING EXECUTED
} else if (this->kq.is_read_available(i)) {
int len;
std::cout << "READ" << std::endl;
// memset(buf, 0, sizeof(buf));
if ((len = recv(fd, buf, sizeof(buf), 0)) == 0) {
std::cout << "READ: FD CLOSED = " << fd << std::endl;
close(fd);
}
else if (len > 0)
{
}
std::cout << "READ: LEN = " << len << std::endl;
} else if (this->kq.is_write_available(i)) {
int len = 0;
if ((len = send(fd, index_html, strlen(index_html), 0)) != 0) {
}
std::cout << "WRITE: LEN = " << len << std::endl;
}
}
}
and kqueue class:
/***********************************************************************
* FILENAME : Kqueue.cpp
*
* DESCRIPTION :
* This File is the implementation of the functions
* Defined in Kqueue.hpp
*
**/
# include "./Kqueue.hpp"
# include "../../OutputColors.hpp"
/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Kqueue::Kqueue()
{
this->_kq = kqueue();
std::cout << "KQUEUE CREATED" << std::endl;
this->test_error(this->_kq, "Creating Kqueue :");
this->_n_ev = 0;
}
webserv::Kqueue::~Kqueue()
{
close(this->_kq);
}
/************************ MEMBER FUNCTIONS ************************/
void webserv::Kqueue::set_event(int fd, int filter, int flags, void *udata)
{
EV_SET(&this->_ev_set, fd, filter, flags, 0, 0, udata);
}
void webserv::Kqueue::add_event(void)
{
int ret;
ret = kevent(this->_kq, &this->_ev_set, 1, NULL, 0, NULL);
this->test_error(ret, "Kqueue/add_even functions");
}
int webserv::Kqueue::get_event(void)
{
this->_n_ev = kevent(this->_kq, NULL, 0, this->_ev_list, __EV_LIST_SIZE__, NULL);
this->test_error(this->_n_ev, "Kqueue/get_event function:");
return (this->_n_ev);
}
void webserv::Kqueue::create_event(int fd, int filter, int flags, void *udata)
{
this->set_event(fd, filter, flags, udata);
this->add_event();
}
bool webserv::Kqueue::isEOF(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/isEOF function:");
return (this->_ev_list[index].flags & EV_EOF);
}
bool webserv::Kqueue::is_read_available(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/is_read_available function:");
return (this->_ev_list[index].filter == EVFILT_READ);
}
bool webserv::Kqueue::is_write_available(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/is_write_available function:");
return (this->_ev_list[index].filter == EVFILT_WRITE);
}
void webserv::Kqueue::test_error(int fd, const std::string &str)
{
if (fd < 0)
{
std::cerr << RED << str << " ";
perror("The following error occured: ");
std::cerr << RESET;
exit(EXIT_FAILURE);
}
}
/************************ GETTERS/SETTERS ************************/
struct kevent *webserv::Kqueue::get_event_list()
{
return (this->_ev_list);
}
int &webserv::Kqueue::get_kq()
{
return (this->_kq);
}
int webserv::Kqueue::get_fd(int index)
{
if (this->_n_ev <= index)
this->test_error(-1, "Kqueue/get_ev_list function:");
return (this->_ev_list[index].ident);
}
void webserv::Kqueue::set_kqueue(int fd)
{
this->_kq = fd;
}
Does anyone know why the WRITE comes before the READ in my case, I'm expecting to read the request, then sending the response
In order for it to be possible to read from the socket, first the other side has to detect that the connection is complete, then it has to compose its query and put it on the wire. Then your side has to receive the information and process it. Only then it is possible to read from the socket.
In order for it to be possible to write to the socket, you have to detect that the connection is complete. That's it. If the connection is complete, it's possible to write.
It's not surprising that it's possbile to write to the socket before it's possible to read from it. The question is -- why is your code checking if it's possible to write to the socket when you don't want to write to the socket? Also, why does your code write to the socket just because it's possible to do so even when you haven't even received a query from the other side?
If you have no data to write to the other side because you haven't even received a query from the other side yet, why are you checking whether or not it's possible to write on the socket? You don't want to write even if it's possible, so why check?
I'm working on a simple async socket client built on top of winsock with io completion ports
it sometimes works and sometimes blocks with strange behaviours
this is the design of the async process :
there are global iocp threads running to receive the completion packets and notify submitters
the submitters use QueueUserApc routine to make the io call in the context of one of the waiting thread
the apc routine makes the async io call and the the a waiter thread should receive the result and notify the issuer
this is my simple wrapper for the io completion ports
template <class T, auto CloseFn>
struct HandleDeleter
{
using pointer = T;
void operator ()(pointer handle) { CloseFn(handle); }
};
using Handle = std::unique_ptr<void, HandleDeleter<HANDLE, CloseHandle>>;
struct IoContext : public OVERLAPPED
{
IoContext()
{
memset(this, 0, sizeof(OVERLAPPED));
}
};
struct CompletionResult
{
CompletionResult() : BytesTransferred(0), Key(0), Ctx(nullptr) {}
CompletionResult(unsigned long bytes, uintptr_t key, IoContext* ctx) : BytesTransferred(bytes), Key(key), Ctx(ctx) {}
unsigned long BytesTransferred;
uintptr_t Key;
IoContext *Ctx;
};
class IoPort
{
Handle port_handle;
public:
IoPort()
{}
IoPort(Handle&& port) : port_handle(std::move(port))
{}
IoPort(IoPort&& rhs) : port_handle(std::move(rhs.port_handle))
{}
IoPort& operator=(IoPort&& rhs)
{
port_handle = std::move(rhs.port_handle);
return *this;
}
bool Create(unsigned int max_threads = 0);
bool AddToPort(Handle& file, uintptr_t key);
bool AddToPort(SOCKET sock, uintptr_t key);
bool GetResultOrApc(CompletionResult& result, DWORD WaitTimeMs);
void Close()
{
port_handle.reset();
}
};
bool IoPort::Create(unsigned int max_threads)
{
port_handle.reset(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, max_threads));
return bool(port_handle);
}
bool IoPort::AddToPort(Handle & file, uintptr_t key)
{
return CreateIoCompletionPort(file.get(), port_handle.get(), key, 0) != nullptr;
}
bool IoPort::AddToPort(SOCKET sock, uintptr_t key)
{
return CreateIoCompletionPort((HANDLE)sock, port_handle.get(), key, 0) != nullptr;
}
bool IoPort::GetResultOrApc(CompletionResult & result, DWORD WaitTimeMs)
{
OVERLAPPED_ENTRY entry = { 0 };
DWORD count = 0;
BOOL wait_result = GetQueuedCompletionStatusEx(port_handle.get(), &entry, 1, &count, WaitTimeMs, TRUE);
if (entry.lpOverlapped)
{
result.Key = entry.lpCompletionKey;
result.BytesTransferred = entry.dwNumberOfBytesTransferred;
result.Ctx = (IoContext*)entry.lpOverlapped;
}
return wait_result;
}
then this is the global iocp threads that starts before entering main function
struct IOCPThreads
{
iocp::IoPort Port;
std::vector<std::thread> IoThreads;
bool Exit = false;
IOCPThreads()
{
if (!Port.Create())
std::cout << "[!] failed to open the port , error : " << GetLastError() << std::endl;
auto num = std::thread::hardware_concurrency();
IoThreads.reserve(num);
std::stringstream thd_ids;
thd_ids << "threads ids : { ";
for (auto i : range(0u, num))
{
IoThreads.emplace_back(std::thread(&IOCPThreads::IoThread, this));
thd_ids << IoThreads[i].get_id() << ", ";
}
auto str = thd_ids.str();
str.pop_back();
str.pop_back();
str += " }";
std::cout << str << std::endl;
}
~IOCPThreads()
{
Exit = true;
for (auto& thd : IoThreads)
if (thd.joinable())
thd.join();
}
void IoThread()
{
while (!Exit)
{
iocp::CompletionResult result;
Port.GetResultOrApc(result, 10);
if (GetLastError() == WAIT_IO_COMPLETION)
std::cout << "[*] received an apc" << std::endl; // sometimes print and sometimes no
if (!result.Ctx)
continue;
DWORD transeferred, Flags;
std::unique_ptr<ClientIoCtx> ctx((ClientIoCtx*)result.Ctx);
WSAGetOverlappedResult(ctx->sock->GetHandle().get(), ctx.get(), &transeferred, FALSE, &Flags);
int WsaError = WSAGetLastError();
if (ctx->op == ClientIoOp::Recv)
{
std::unique_ptr<ClientIoRecvCtx> RecvCtx = unique_static_cast<ClientIoRecvCtx>(ctx);
RecvCtx->OnResult(*RecvCtx->sock, WsaError, std::span{ RecvCtx->buffer, RecvCtx->buffer + RecvCtx->length }, transeferred);
}
}
}
};
IOCPThreads ClientIoThreads;
and this is the socket implemention :
enum class async_status_code : unsigned int
{
Pending,
Finished,
Error,
};
struct AsyncResult
{
async_status_code code;
unsigned int transferred;
AsyncResult() : code(async_status_code::Error), transferred(0)
{}
AsyncResult(async_status_code c, unsigned int s) : code(c), transferred(s)
{}
bool IsPending() const
{
return code == async_status_code::Pending;
}
bool IsFinished() const
{
return code == async_status_code::Finished;
}
bool IsFailed() const
{
return code == async_status_code::Error;
}
};
using AsyncSendFunc = std::function<void(Socket& sock, int ErrorCode, std::span<const char> Buffer, DWORD transeferred)>;
enum class SendRecvFlags
{
UnSpecefied = 0,
MsgDontRoute = 0x4,
MsgOOB = 0x1,
MsgPeek = 0x2,
MsgWaitAll = 0x8,
MsgPushImmediate = 0x20,
};
enum class ClientIoOp
{
Send,
};
struct ApcResult
{
async_status_code code;
DWORD transeferred;
int error;
};
struct ClientIoCtx : public IoContext
{
Socket *sock;
ClientIoOp op;
promise<ApcResult> notifier;
};
struct ClientIoSendCtx : public ClientIoCtx
{
ClientIoSendCtx() { op = ClientIoOp::Send; }
const char *buffer;
int length;
SendRecvFlags flags;
AsyncSendFunc OnResult;
};
AsyncResult LIB_NAMESPACE::net::Socket::AsyncSend(const char * buffer, int length, io::IoContext & IoCtx, SendRecvFlags flags)
{
WSABUF buff_vec{ length, (char*)buffer };
DWORD sent = 0;
if (WSASend(sock.get(), &buff_vec, 1, &sent, (DWORD)flags, &IoCtx, nullptr) == 0)
return AsyncResult(async_status_code::Finished, sent);
else if (WSAGetLastError() == WSA_IO_PENDING)
return AsyncResult(async_status_code::Pending, sent);
return AsyncResult();
}
AsyncResult LIB_NAMESPACE::net::Socket::AsyncSend(const char * buffer, int length, const AsyncSendFunc & OnSend, SendRecvFlags flags)
{
ClientIoSendCtx *ctx = new ClientIoSendCtx();
ctx->sock = this;
ctx->buffer = buffer;
ctx->length = length;
ctx->flags = flags;
ctx->OnResult = OnSend;
auto fut = ctx->notifier.get_future(); // notifier is a promise
auto& thd = ClientIoThreads.IoThreads[RandomUInt(0, ClientIoThreads.IoThreads.size() - 1)];
std::cout << "[*] launchin the apc routine in thread : " << thd.get_id() << std::endl; // it's always one of the io threads
auto dwRes = QueueUserAPC(Socket::ApcRoutine, thd.native_handle(), (ULONG_PTR)ctx);
if (!dwRes) // doesn't happen
{
delete ctx;
std::cout << "QueueUserAPC failed with error " << GetLastError() << std::endl;
return AsyncResult();
}
auto result = fut.get(); // --> blocks here because the apc routine doesn't start
WSASetLastError(result.error); // the wsa error is thread local so I transfer it from the apc thread to this thread
return AsyncResult(result.code, result.transeferred);
}
void ApcRoutine(unsigned long long Param)
{
std::cout << "[*] ApcRoutine started" << std::endl; // sometimes is printed and sometimes no
std::unique_ptr<ClientIoCtx> ctx((ClientIoCtx*)Param);
if (ctx->op == ClientIoOp::Send)
{
std::unique_ptr<ClientIoSendCtx> SendCtx = unique_static_cast<ClientIoSendCtx>(ctx);
auto async_result = SendCtx->sock->AsyncSend(SendCtx->buffer, SendCtx->length, *SendCtx, SendCtx->flags);
ApcResult apc_result;
apc_result.code = async_result.code;
apc_result.transeferred = async_result.transferred;
apc_result.error = WSAGetLastError();
SendCtx->notifier.set_value(apc_result);
if (apc_result.code != async_status_code::Error)
SendCtx.release();
}
}
the problem is that the QueuUserApc sometimes doesn't fail but the apc routine doesn't start so the the issuer thread blocks waiting with future::get
I checked the GetLasError() value every time after calling QueuUserApc and it is always 0 so what is wrong here ?
I'm writing an TCP server in Mini-OS(an operation system in xen), it can connect to multiple TCP clients. I wrote a simple code for handling multiple TCP clients , but there is an issue with the code. The issue is I can't get the server to connect more than three active connections. The 4th or more clients could not connect for unknown reasons. I looked around the forums and tried increasing the number limit for MEMP_NUM_TCP_PCB in opt.h (stubdom\lwip-x86_64\include\lwip\opt.h) and it didn't help either.
I'm running a TCP client on Ubuntu. Based on what I saw, the 4th client did seem connected, but an exception was thrown during the "write" function: "Resolver Error 0 (no error)"
How can I solve this problem?
//server code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define MYPORT 1234 // the port users will be connecting to
#define BACKLOG 2// how many pending connections queue will hold
#define BUF_SIZE 1024
int fd_A[BACKLOG]; // accepted connection fd
int conn_amount; // current connection amount
void showclient()
{
int i;
printf("-----> client amount: %d\n", conn_amount);
for (i = 0; i < BACKLOG; i++) {
printf("BACKLOG%d ---> fd = %d\n", i, fd_A[i]);
}
printf("\n\n");
}
int main(void)
{
sleep(1);
printf("start server\n");
int sock_fd, new_fd; // listen on sock_fd, new connection on new_fd
struct sockaddr_in server_addr; // server address information
struct sockaddr_in client_addr; // connector's address information
socklen_t sin_size;
int yes = 1;
char buf[BUF_SIZE];
int ret;
int i;
if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
//if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
/*if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
//perror("setsockopt");
//exit(1);
}
if (fcntl(sock_fd, F_SETFL, O_NONBLOCK) == -1) {
printf("Set server socket nonblock failed\n");
exit(1);
}*/
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET; // host byte order
server_addr.sin_port = htons(MYPORT); // short, network byte order
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // automatically fill with my IP
//memset(server_addr.sin_zero, '0', sizeof(server_addr.sin_zero));
if (bind(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind");
exit(1);
}
printf("listen...\n");
if (listen(sock_fd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
printf("listen port %d\n", MYPORT);
fd_set fdsr, wfds, efds;
int maxsock;
struct timeval tv;
conn_amount = 0;
sin_size = sizeof(client_addr);
maxsock = sock_fd;
while (1)
{
sleep(1); // it's necessary
// initialize file descriptor set
FD_ZERO(&fdsr);
FD_ZERO(&wfds);
//FD_ZERO(&efds);
FD_SET(sock_fd, &fdsr); // add fd
FD_SET(sock_fd, &wfds); // add fd
//FD_SET(sock_fd, &efds); // add fd
// timeout setting
tv.tv_sec = 30;
tv.tv_usec = 0;
// add active connection to fd set
for (i = 0; i < BACKLOG; i++) {
if (fd_A[i] != 0) {
FD_SET(fd_A[i], &fdsr);
}
}
//printf("before select!!!!!!!!!!!! ret = %d\n", ret);
if ((select(maxsock + 1, &fdsr, &wfds, (fd_set*) 0, (struct timeval*) 0)) < 0) {
perror("select");
break;
}
// check every fd in the set
for (i = 0; i < conn_amount; i++)
{
if (FD_ISSET(fd_A[i], &fdsr)) // check which fd is ready
{
ret = recv(fd_A[i], buf, sizeof(buf), 0);
if (ret <= 0)
{ // client close
printf("ret : %d and client[%d] close\n", ret, i);
close(fd_A[i]);
FD_CLR(fd_A[i], &fdsr); // delete fd
fd_A[i] = 0;
conn_amount--;
}
else
{ // receive data
if (ret < BUF_SIZE)
memset(&buf[ret], '\0', 1); // add NULL('/0')
printf("client[%d] send:%s\n", i, buf);
}
}
}
// check whether a new connection comes
if (FD_ISSET(sock_fd, &fdsr)) // accept new connection
{
new_fd = accept(sock_fd, (struct sockaddr *)&client_addr, &sin_size);
if (new_fd <= 0)
{
perror("accept");
continue;
}
// add to fd queue
if (conn_amount < BACKLOG)
{
fd_A[conn_amount++] = new_fd;
printf("------> new connection client[%d] %s:%d\n", conn_amount,
inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
if (new_fd > maxsock) // update the maxsock fd for select function
maxsock = new_fd;
}
else
{
printf("max connections arrive, exit\n");
send(new_fd, "bye", 4, 0);
close(new_fd);
break;
}
}
//showclient();
}
// close other connections
for (i = 0; i < BACKLOG; i++)
{
if (fd_A[i] != 0)
{
close(fd_A[i]);
}
}
exit(0);
}
//client code
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <malloc.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define RES_LENGTH 10240
int connect_socket(char * server,int serverPort);
int send_msg(int sockfd,char * sendBuff);
char * recv_msg(int sockfd);
int close_socket(int sockfd);
int main(int argc, char ** argv)
{
int sockfd[1024] = {0};
char sendMsg[30]="zhangchengfei\r\n\r";
char* res;
int port = 1234;
char ip[128] = {0};
strncpy(ip, "10.107.19.62", 128);
if(argc > 2)
{
strncpy(ip, argv[1], 128);
port = atoi(argv[2]);
printf("Input IP: %s, port : %d\n", ip, port);
}
else if(argc > 1)
{
//port = atoi(argv[1]);
//printf("Input port : %d\n", port);
//
int num_client = atoi(argv[1]);
int i = 0;
for (i = 0; i <= num_client; i++) {
printf("start connect %d\n", i + 1);
sockfd[i]=connect_socket(ip, port);
printf("connect %d OK\n", i + 1);
getchar();
}
for (i = 0; i <= num_client; i++) {
send_msg(sockfd[i], sendMsg);
/* res=recv_msg(sockfd); */
printf("client %d send msg = %s\n", i + 1, sendMsg);
//printf(res);
//free(res);
getchar();
}
for (i = 0; i <= num_client; i++) {
close_socket(sockfd[i]);
printf("close socket %d\n", i + 1);
}
}
return 0;
}
int connect_socket(char * server,int serverPort){
int sockfd=0;
struct sockaddr_in addr;
struct hostent * phost;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0){
herror("Init socket error!");
return -1;
}
bzero(&addr,sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(serverPort);
addr.sin_addr.s_addr = inet_addr(server);
if(addr.sin_addr.s_addr == INADDR_NONE){
phost = (struct hostent*)gethostbyname(server);
if(phost==NULL){
herror("Init socket s_addr error!");
return -1;
}
addr.sin_addr.s_addr =((struct in_addr*)phost->h_addr)->s_addr;
}
if(connect(sockfd,(struct sockaddr*)&addr, sizeof(addr))<0)
{
perror("Connect server fail!");
return -1;
}
else
return sockfd;
}
int send_msg(int sockfd,char * sendBuff)
{
int sendSize=0;
if((sendSize=send(sockfd,sendBuff,strlen(sendBuff),0))<=0){
herror("Send msg error!");
return -1;
}else
return sendSize;
}
char* recv_msg(int sockfd){
char * response;
int flag=0,recLenth=0;
response=(char *)malloc(RES_LENGTH);
memset(response,0,RES_LENGTH);
for(flag=0;;)
{
printf("======recv data:\n");
if(( recLenth=recv(sockfd,response+flag,RES_LENGTH-flag,0))==-1 )
{
free(response);
printf("Return value : %d\n", recLenth);
perror("Recv msg error : ");
return NULL;
}
else if(recLenth==0)
break;
else
{
printf("%d char recieved data : %s.\n", recLenth, response+flag);
flag+=recLenth;
recLenth=0;
}
}
printf("Return value : %d\n", recLenth);
response[flag]='0';
return response;
}
int close_socket(int sockfd)
{
close(sockfd);
return 0;
}
I have solved this problem caused by a Makefile bug in ./stubdom, after executing make crossclean , I found the .o files still existed in lwip-x86_64 folder. So I add a command find . -name "*.o" | xargs rm -f in Makefile and then anything is OK.
The reason is that lwip configure is given by the macro definition, macro definition have been replaced at the pre-compilation stage, so if I modify the lwip configure and did not delete the .o files, there is no effect. Following is the macro definitions I have modified in opt.h.
MEMP_NUM_TCP_PCB 100
MEMP_NUM_TCP_PCB_LISTEN 100
MEMP_NUM_NETCONN 100
Now the server can break through the connection limitations and more than 3 active TCP connections can be established, but sad that we have encountered another problem, the server side only can receive 61 clients of the connection requests. If exceeding the clients number, server side error will be reported as follows:
ASSERTION FAILED: mbox->reader != mbox->writer at lwip-arch.c:124.
Do_exit called!
base is 0x29fe78 caller is 0x4d49d
base is 0x29fe98 caller is 0x5a05a
base is 0x29fec8 caller is 0x5a153
base is 0x29fef8 caller is 0x634a1
base is 0x29ff28 caller is 0x65074
base is 0x29ff78 caller is 0x5d0dd
base is 0x29ffc8 caller is 0x59822
base is 0x29ffe8 caller is 0x33da
How can I solve the above problem?
I want to stream JPEG images or motion-JPEG file through live 555. But the problem is that in live 555 implementation for Jpegs is not available. Anyone can help ??
You can find a implementation that was posted to the devel mailing list http://lists.live555.com/pipermail/live-devel/2012-February/014672.html.
The code and a sample is available but this modification was rejected by live555 maintainer.
First we need to implement an MJPEGVideoSource than can feed a JPEGVideoRTPSink.
#include "JPEGVideoSource.hh"
class MJPEGVideoSource : public JPEGVideoSource
{
public:
static MJPEGVideoSource* createNew (UsageEnvironment& env, FramedSource* source)
{
return new MJPEGVideoSource(env,source);
}
virtual void doGetNextFrame()
{
if (m_inputSource)
m_inputSource->getNextFrame(fTo, fMaxSize, afterGettingFrameSub, this, FramedSource::handleClosure, this);
}
virtual void doStopGettingFrames()
{
FramedSource::doStopGettingFrames();
if (m_inputSource)
m_inputSource->stopGettingFrames();
}
static void afterGettingFrameSub(void* clientData, unsigned frameSize,unsigned numTruncatedBytes,struct timeval presentationTime,unsigned durationInMicroseconds)
{
MJPEGVideoSource* source = (MJPEGVideoSource*)clientData;
source->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds);
}
void afterGettingFrame(unsigned frameSize,unsigned numTruncatedBytes,struct timeval presentationTime,unsigned durationInMicroseconds)
{
int headerSize = 0;
bool headerOk = false;
fFrameSize = 0;
for (unsigned int i = 0; i < frameSize ; ++i)
{
// SOF
if ( (i+8) < frameSize && fTo[i] == 0xFF && fTo[i+1] == 0xC0 )
{
m_height = (fTo[i+5]<<5)|(fTo[i+6]>>3);
m_width = (fTo[i+7]<<5)|(fTo[i+8]>>3);
}
// DQT
if ( (i+5+64) < frameSize && fTo[i] == 0xFF && fTo[i+1] == 0xDB)
{
if (fTo[i+4] ==0)
{
memcpy(m_qTable, fTo + i + 5, 64);
m_qTable0Init = true;
}
else if (fTo[i+4] ==1)
{
memcpy(m_qTable + 64, fTo + i + 5, 64);
m_qTable1Init = true;
}
}
// End of header
if ( (i+1) < frameSize && fTo[i] == 0x3F && fTo[i+1] == 0x00 )
{
headerOk = true;
headerSize = i+2;
break;
}
}
if (headerOk)
{
fFrameSize = frameSize - headerSize;
memmove( fTo, fTo + headerSize, fFrameSize );
}
fNumTruncatedBytes = numTruncatedBytes;
fPresentationTime = presentationTime;
fDurationInMicroseconds = durationInMicroseconds;
afterGetting(this);
}
virtual u_int8_t type() { return 1; };
virtual u_int8_t qFactor() { return 128; };
virtual u_int8_t width() { return m_width; };
virtual u_int8_t height() { return m_height; };
u_int8_t const* quantizationTables( u_int8_t& precision, u_int16_t& length )
{
length = 0;
precision = 0;
if ( m_qTable0Init && m_qTable1Init )
{
precision = 8;
length = sizeof(m_qTable);
}
return m_qTable;
}
protected:
MJPEGVideoSource(UsageEnvironment& env, FramedSource* source) : JPEGVideoSource(env),
m_inputSource(source),
m_width(0),
m_height(0),
m_qTable0Init(false),
m_qTable1Init(false)
{
memset(&m_qTable,0,sizeof(m_qTable));
}
virtual ~MJPEGVideoSource()
{
Medium::close(m_inputSource);
}
protected:
FramedSource* m_inputSource;
u_int8_t m_width;
u_int8_t m_height;
u_int8_t m_qTable[128];
bool m_qTable0Init;
bool m_qTable1Init;
};
Next we can use it as a video source in order to build a simple RTSP server:
#include "liveMedia.hh"
#include "BasicUsageEnvironment.hh"
#include "GroupsockHelper.hh"
#include "MJPEGVideoSource.hh"
char const* inputFileName = "test.mjpeg";
int main(int argc, char** argv) {
// Begin by setting up our usage environment:
TaskScheduler* scheduler = BasicTaskScheduler::createNew();
UsageEnvironment* env = BasicUsageEnvironment::createNew(*scheduler);
// Create 'groupsocks' for RTP and RTCP:
struct in_addr destinationAddress;
destinationAddress.s_addr = chooseRandomIPv4SSMAddress(*env);
const unsigned short rtpPortNum = 18888;
const unsigned short rtcpPortNum = rtpPortNum+1;
const unsigned char ttl = 255;
const Port rtpPort(rtpPortNum);
const Port rtcpPort(rtcpPortNum);
Groupsock rtpGroupsock(*env, destinationAddress, rtpPort, ttl);
rtpGroupsock.multicastSendOnly(); // we're a SSM source
Groupsock rtcpGroupsock(*env, destinationAddress, rtcpPort, ttl);
rtcpGroupsock.multicastSendOnly(); // we're a SSM source
// Create a 'JPEG Video RTP' sink from the RTP 'groupsock':
RTPSink* videoSink = JPEGVideoRTPSink::createNew(*env, &rtpGroupsock);
// Create (and start) a 'RTCP instance' for this RTP sink:
const unsigned estimatedSessionBandwidth = 5000; // in kbps; for RTCP b/w share
const unsigned maxCNAMElen = 100;
unsigned char CNAME[maxCNAMElen+1];
gethostname((char*)CNAME, maxCNAMElen);
CNAME[maxCNAMElen] = '\0'; // just in case
RTCPInstance* rtcp = RTCPInstance::createNew(*env, &rtcpGroupsock,
estimatedSessionBandwidth, CNAME,
videoSink, NULL /* we're a server */,
True /* we're a SSM source */);
// Note: This starts RTCP running automatically
RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);
if (rtspServer == NULL) {
*env << "Failed to create RTSP server: " << env->getResultMsg() << "\n";
exit(1);
}
ServerMediaSession* sms = ServerMediaSession::createNew(*env, "testStream", inputFileName,"Session streamed by \"testMJPEGVideoStreamer\"",
True /*SSM*/);
sms->addSubsession(PassiveServerMediaSubsession::createNew(*videoSink, rtcp));
rtspServer->addServerMediaSession(sms);
char* url = rtspServer->rtspURL(sms);
*env << "Play this stream using the URL \"" << url << "\"\n";
delete[] url;
// Start the streaming:
*env << "Beginning streaming...\n";
// Open the input file as a 'byte-stream file source':
ByteStreamFileSource* fileSource = ByteStreamFileSource::createNew(*env, inputFileName);
if (fileSource == NULL) {
*env << "Unable to open file \"" << inputFileName
<< "\" as a byte-stream file source\n";
exit(1);
}
// Create the MJPEG video source:
MJPEGVideoSource* videoSource = MJPEGVideoSource::createNew(*env, fileSource);
// Finally, start playing:
*env << "Beginning to read from file...\n";
videoSink->startPlaying(*videoSource, NULL, NULL);
env->taskScheduler().doEventLoop();
return 0;
}
Hope you have done it but if not-
see this Jpeg Streaming using live555
This is doing the same thing as you have asked to stream the images/Jpegs.
For MJpegs you'll have to do the same process.
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);
}