QueuUserAPC sometimes doesn't launc an apc routine in a thread waiting with GetQueuedCompletionStatusEx - sockets

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 ?

Related

invalid conversion from 'int' to 'int*' [-fpermissive]

I am new to C++ language and I have no idea of pointers and their usage. I'm facing the error "[Error] invalid conversion from 'int' to 'int*' [-fpermissive]" while compiling.
Here is the code.
#include <iostream>
#define TRUE 1
#define FALSE 0
using namespace std;
class tree
{
private:
struct node
{
node *l;
int data;
node *r;
} *p;
public:
tree();
void search(int n, int &found, int *&parent);
void insert(int n);
void traverse();
void in(node *q);
void pre(node *q);
void post(node *q);
int compare(node *pp, node *qq);
void operator=(tree t);
int operator==(tree t);
node *copy(node *q);
};
tree ::tree()
{
p = NULL;
}
void tree ::search(int n, int &found, int *&parent)
{
node *q;
found = FALSE;
parent = TRUE;
if (p == NULL)
return;
q = p;
while (q != NULL)
{
if (q->data == n)
{
found = TRUE;
return;
}
if (q->data > n)
{
parent = q;
q = q->l;
}
else
{
parent = q;
q = q->r;
}
}
}
void tree::insert(int n)
{
int found;
node *t, *parent;
search(n, found, parent);
if (found == TRUE)
{
cout << endl << "Such a node already exists";
}
else
{
t = new node;
t->data = n;
t->l = NULL;
t->r = NULL;
if (parent == NULL)
{
p = t;
}
else
{
parent->data > n ? parent->l : parent->r = t;
}
}
}
void tree::traverse()
{
int choice;
cout << endl
<< "1. Inorder" << endl
<< "2. Preorrder" << endl
<< "3. Postorder" << endl
<< "4. Your choice";
cin >> choice;
switch (choice)
{
case 1:
in(p);
break;
case 2:
pre(p);
break;
case 3:
post(p);
break;
}
}
void tree::in(node *q)
{
if (q != NULL)
{
in(q->l);
cout << "\t" << q->data;
in(q->r);
}
}
void tree::pre(node *q)
{
if (q != NULL)
{
cout << "\t" << q->data;
pre(q->l);
pre(q->r);
}
}
void tree ::post(node *q)
{
if (q != NULL)
{
post(q->l);
post(q->r);
cout << "\t" << q->data;
}
}
int tree::operator==(tree t)
{
int flag;
flag = compare(p, t.p);
return (flag);
}
int tree::compare(node *pp, node *qq)
{
static int flag;
if ((pp == NULL) && (qq != NULL))
{
if ((pp != NULL) && (qq != NULL))
{
if (pp->data != qq->data)
{
flag = FALSE;
}
else
{
compare(pp->l, qq->l);
compare(pp->r, qq->r);
}
}
}
return (flag);
}
void tree::operator=(tree t)
{
p = copy(t.p);
}
tree::node *tree::copy(node *q)
{
if (q != NULL)
{
t = new node;
t->data = q->data;
t->l = copy(q->l);
t->r= copy(q->r);
return (t);
}
else
{
return(NULL);
}
}
int main()
{
tree tt, ss;
int i, num;
for (i = 0; i <= 6; i++)
{
cout << endl
<< "Enter the data for the node to be inserted";
cin >> num;
tt.insert(num);
}
tt.traverse();
ss = tt;
ss.traverse();
if (ss == tt)
cout << endl
<< "Trees are equal";
else
cout << endl
<< "Trees are not equal";
return 0;
}
I was trying to implement Binary search tree using class and traverse the tree using any traversal scheme. In addition to it the class must have capability to copy the contents from one tree to another and compare the contents of two binary trees.

read event is received before the write one in kqueue

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?

Unable to connect second client in server c++

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.

Want to reset integers using virtual class function

The function I want works within the class butt won't apply to main. Must maintain the initial (Entity *entity = new Nummchange(flarb);)
#include <iostream>
using namespace std;
class Entity
{
public:
Entity(){}
~Entity(){}
virtual int reset(int NUMM) = NULL;
protected:
private:
};
class Nummchange : public Entity
{
public:
Nummchange(int NUMM);
~Nummchange();
int reset(int NUMM);
protected:
private:
int numm;
};
Nummchange::Nummchange(int NUMM)
{
}
Nummchange::~Nummchange()
{
}
int Nummchange::reset(int NUMM)
{
numm = 50;
NUMM = numm;
std::cout << "\nnumm+++++++"<< numm << "\n" << std::endl;
return numm;
}
int main()
{
int flarb = 50;
Entity *entity = new Nummchange(flarb);
while (flarb >= 0)
{
flarb--;
cout << flarb;
if(flarb == 0)
{
entity->reset(flarb);
std::cout << "flarb+++++++"<< flarb << "\n" << std::endl;
}
}
system("pause");
return 0;
}
Success is if the while loop continues perpetually.
int reset(int NUMM); method should take reference of integer type as below.
int reset(int &NUMM);
Make sure that you change the parameter to be reference of integer in all the three places of the method use in the program.

JPEG streaming with live555

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.