How to store device id in web service in windows phone? - web-services

this is my web service url
http://www.newsquizapp.com/webservice/get_question
Parameter :
1. device_id
2. quiz_type
Method: post
i already retrieve device_id & quiz_type
but my problem is how to send device_id & quiz_type so that the device id is store in web service.
void SendPost()
{
var url = "http://www.newsquizapp.com/webservice/get_question";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest);
}
void GetRequestStreamCallback(IAsyncResult callbackResult)
{
HttpWebRequest webRequest = (HttpWebRequest)callbackResult.AsyncState;
Stream postStream = webRequest.EndGetRequestStream(callbackResult);
// static device id
string postData = "device_id=001&quiz_type=all";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest);
}
void GetResponseCallback(IAsyncResult callbackResult)
{
try
{
HttpWebRequest webRequest = (HttpWebRequest)callbackResult.AsyncState;
HttpWebResponse response;
response = (HttpWebResponse)webRequest.EndGetResponse(callbackResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
var Response = streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
}
catch (WebException e)
{
// Error treatment
// ...
}
}
public void MainPage_Loaded(object sender, RoutedEventArgs e)
{
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(download);
client.DownloadStringAsync(new Uri("http://www.newsquizapp.com/webservice/get_question"));
}
public void download(object sender, DownloadStringCompletedEventArgs e)
{
var objMain = JsonConvert.DeserializeObject<Main>(e.Result);
question = objMain.questions;
DisplayQuestion();
}
protected void DisplayQuestion()
{
rb1.Visibility = Visibility.Visible;
rb2.Visibility = Visibility.Visible;
rb3.Visibility = Visibility.Visible;
rb4.Visibility = Visibility.Visible;
Question objQue = question[counter];
txtquestion.Text = objQue.questionTitle;
rb1.Content = objQue.answers[0].answer;
rb2.Content = objQue.answers[1].answer;
rb3.Content = objQue.answers[2].answer;
if (objQue.answers.Count == 3)
{
rb4.Visibility = Visibility.Collapsed;
}
else
{
rb4.Visibility = Visibility.Visible;
rb4.Content = objQue.answers[3].answer;
}
}
protected void radio_checked(object sender, RoutedEventArgs e)
{
btnFinish.Visibility = Visibility.Collapsed;
btnSubmit.Visibility = Visibility.Visible;
}
protected void btnsubmit_click(object sender, RoutedEventArgs e)
{
Question que = question[counter];
var correctAnswerId = que.correctAnswerId;
string answer = string.Empty;
if (que.answers[0].answerId == correctAnswerId)
{
answer = que.answers[0].answer;
}
if (que.answers[1].answerId == correctAnswerId)
{
answer = que.answers[1].answer;
}
if (que.answers[2].answerId == correctAnswerId)
{
answer = que.answers[2].answer;
}
if (que.answers.Count == 3)
{
rb4.Visibility = Visibility.Collapsed;
}
else if (que.answers[3].answerId == correctAnswerId)
{
answer = que.answers[3].answer;
}
if (rb1.IsChecked == true && que.answers[0].answerId == correctAnswerId)
{
txtanswer.Text = que.answers[0].answer;
rb1.Visibility = Visibility.Collapsed;
rb2.Visibility = Visibility.Collapsed;
rb3.Visibility = Visibility.Collapsed;
rb4.Visibility = Visibility.Collapsed;
}
else if (rb1.IsChecked == true && que.answers[0].answerId != correctAnswerId)
{
rb1.Visibility = Visibility.Visible;
rb2.Visibility = Visibility.Collapsed;
rb3.Visibility = Visibility.Collapsed;
rb4.Visibility = Visibility.Collapsed;
txtanswer.Text = answer;
}
else if (rb2.IsChecked == true && que.answers[1].answerId == correctAnswerId)
{
txtanswer.Text = que.answers[1].answer;
rb1.Visibility = Visibility.Collapsed;
rb2.Visibility = Visibility.Collapsed;
rb3.Visibility = Visibility.Collapsed;
rb4.Visibility = Visibility.Collapsed;
}
else if (rb2.IsChecked == true && que.answers[1].answerId != correctAnswerId)
{
rb1.Visibility = Visibility.Collapsed;
rb2.Visibility = Visibility.Visible;
rb3.Visibility = Visibility.Collapsed;
rb4.Visibility = Visibility.Collapsed;
txtanswer.Text = answer;
}
else if (rb3.IsChecked == true && que.answers[2].answerId == correctAnswerId)
{
txtanswer.Text = que.answers[2].answer;
rb1.Visibility = Visibility.Collapsed;
rb2.Visibility = Visibility.Collapsed;
rb3.Visibility = Visibility.Collapsed;
rb4.Visibility = Visibility.Collapsed;
}
else if (rb3.IsChecked == true && que.answers[2].answerId != correctAnswerId)
{
rb1.Visibility = Visibility.Collapsed;
rb2.Visibility = Visibility.Collapsed;
rb3.Visibility = Visibility.Visible;
rb4.Visibility = Visibility.Collapsed;
txtanswer.Text = answer;
}
else if (que.answers.Count == 3)
{
rb4.Visibility = Visibility.Collapsed;
}
else if (rb4.IsChecked == true && que.answers[3].answerId == correctAnswerId)
{
txtanswer.Text = que.answers[3].answer;
rb1.Visibility = Visibility.Collapsed;
rb2.Visibility = Visibility.Collapsed;
rb3.Visibility = Visibility.Collapsed;
rb4.Visibility = Visibility.Collapsed;
}
else if (rb4.IsChecked == true && que.answers[3].answerId != correctAnswerId)
{
rb1.Visibility = Visibility.Collapsed;
rb2.Visibility = Visibility.Collapsed;
rb3.Visibility = Visibility.Collapsed;
rb4.Visibility = Visibility.Visible;
txtanswer.Text = answer;
}
btnNext.Visibility = Visibility.Visible;
}
protected void btnnext_click(object sender, RoutedEventArgs e)
{
counter++;
if (counter >= question.Count)
{
txtanswer.Text = "no more question right now....";
}
else
{
DisplayQuestion();
}
}
}
once the user device id stores in database, they will not get the same question if user close the app & again open it...

If you just want to POST data to a web service you can use WebClient class. It is the simplest way to achieve what you are looking to do.
Example:
Uri uri = new Uri("http://www.newsquizapp.com/webservice/get_question");
string data = "device_id=123&quiz_type=all";
WebClient wc = new WebClient();
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
wc.UploadStringAsync(uri, data);
wc.UploadStringCompleted += wc_UploadComplete;
public void wc_UploadComplete(object sender, UploadStringCompletedEventArgs e)
{
string result = e.Result.ToString();
MessageBox.Show(result);
}
Try this out. Hope it helps.

Maybe a HTTPRequest is what you are looking for.
http://dotnet-snippets.de/snippet/simple-web-request-with-web-response/215

Http Post for Windows Phone 8
Check the answer from nemesisfixx.
I found it helpful.
If you have access to the webservice code, you can modify it to carry the Device_uid as a url parameter and thus avoid all the extra work. I did so.

Related

a way to rotate the charatcer to the corresponding inputs glm

I have been trying to rotate (and have a smooth rotation) the charcter to the corresponding user Inputs but I am allways having a problem and i need to know how to solve it.Since the nonsmooth rotation worked I am trying to make one that is smooth.
the code i have used:
if (LeftKey == true)
{
if (RightKey == true)
{
PlayerOrientation = 0;
}else
{
PlayerOrientation = 45;
}
}else
{
if (RightKey == true)
{
PlayerOrientation = -45;
}else
{
PlayerOrientation = 0;
}
}
}else if (RightKey == false && LeftKey == true)
{
if (DownKey == true)
{
if (UpKey == true)
{
PlayerOrientation = 90;
}else
{
PlayerOrientation = 135;
}
}else
{
if (UpKey == true)
{
PlayerOrientation = 45;
}else
{
PlayerOrientation = 90;
}
}
}else if (UpKey == false && DownKey == true)
{
if (LeftKey == true)
{
if (RightKey == true)
{
PlayerOrientation = 180;
}else
{
PlayerOrientation = 135;
}
}else
{
if (RightKey == true)
{
PlayerOrientation = -135;
}else
{
PlayerOrientation = 180;
}
}
}else if (LeftKey == false && RightKey == true)
{
if (DownKey == true)
{
if (UpKey == true)
{
PlayerOrientation = -90;
}else
{
PlayerOrientation = -135;
}
}else
{
if (UpKey == true)
{
PlayerOrientation = -45;
}else
{
PlayerOrientation = -90;
}
}
}
if (UpKey == true || DownKey == true || RightKey == true || LeftKey == true)
{
if (ThePlayerOrientation != PlayerOrientation)
{
float diffrence = (PlayerOrientation - ThePlayerOrientation) / 20;
thePlayerPos += diffrence;
if (PlayerOrientation == thePlayerPos)
{
ThePlayerOrientation = PlayerOrientation;
thePlayerPos = PlayerOrientation;
}
}
}
if someone could help me it would be really helpfull.

Add actual timestamp to mp4 using ffmpeg

I'm using ffmpeg to write an h264 stream to a mp4 file.
Everything is working, but now I need to embed to this file the actual timestamp in milliseconds of each frame.
Is it possible?
This is my code:
void mp4_file_create(mp4_par * par, t_image * img_in)
{
AVCodec * codec = NULL;
AVCodecContext * cc_in;
AVFormatContext * av_fmt_ctx_out;
AVStream * av_stream;
AVPacket av_pkt;
AVFormatContext * ifmt_ctx;
unsigned long long last_frame_ts_utc;
unsigned long long last_frame_ts_absolute;
unsigned long long last_pts;
t_mp4_dict_metadata metadata;
char file_name[1024];
char TSstrdate[128];
av_register_all();
cc_in = NULL;
av_stream = NULL;
if (avformat_alloc_output_context2(&mp4h->av_fmt_ctx_out, NULL, NULL, file_name) < 0) {
trace_error("avformat_alloc_output_context2 failed");
goto FnExit;
}
/* find the H264 RAW encoder */
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
int ret;
AVStream *in_stream = NULL;
if (av_fmt_ctx_in == NULL)
{
trace_error("av_fmt_ctx_in is NULL");
goto FnExit;
}
in_stream = av_fmt_ctx_in->streams[0];
in_stream->codec->width = par.width;
in_stream->codec->height = par.height;
in_stream->codec->coded_width = par.width;
in_stream->codec->coded_height = par.height;
in_stream->codec->bit_rate = 1024;
in_stream->codec->flags = CODEC_FLAG_GLOBAL_HEADER;
in_stream->codec->time_base.num = 1;
in_stream->codec->time_base.den = par.frame_rate;
in_stream->codec->gop_size = par.gop;
in_stream->codec->pix_fmt = AV_PIX_FMT_YUV420P;
av_stream = avformat_new_stream(mp4h->av_fmt_ctx_out, in_stream->codec->codec);
if (!av_stream) {
trace_error("Failed allocating output stream");
goto FnExit;
}
ret = avcodec_copy_context(av_stream->codec, in_stream->codec);
if (ret != 0) {
goto FnExit;
}
}
else {
int ret;
av_stream = avformat_new_stream(mp4h->av_fmt_ctx_out, NULL);
if (!av_stream) {
goto FnExit;
}
cc_in = avcodec_alloc_context3(codec);
if (cc_in == NULL) {
goto FnExit;
}
cc_in->width = par.width;
cc_in->height = par.height;
cc_in->bit_rate = 1024;
cc_in->flags = CODEC_FLAG_GLOBAL_HEADER;
cc_in->time_base.num = 1;
cc_in->time_base.den = par.frame_rate;
cc_in->gop_size = par.gop;
cc_in->pix_fmt = AV_PIX_FMT_YUVJ420P;
cc_in->extradata = (unsigned char*)av_mallocz(sizeof(sample_spspps));
cc_in->extradata_size = sizeof(sample_spspps);
memcpy(cc_in->extradata, sample_spspps, cc_in->extradata_size);
ret = avcodec_copy_context(av_stream->codec, cc_in);
if (ret != 0) {
goto FnExit;
}
}
av_stream->codec->codec_tag = 0;
if (av_fmt_ctx_out->oformat->flags & AVFMT_GLOBALHEADER)
av_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
if (!(av_fmt_ctx_out->flags & AVFMT_NOFILE)) {
int ret = avio_open(&av_fmt_ctx_out->pb, file_name, AVIO_FLAG_READ_WRITE);
if (ret < 0) {
trace_error("Could not open output file '%s'", file_name);
goto FnExit;
}
}
av_fmt_ctx_out->streams[0]->time_base.num = 1;
av_fmt_ctx_out->streams[0]->time_base.den = par.frame_rate;
av_fmt_ctx_out->streams[0]->codec->time_base.num = 1;
av_fmt_ctx_out->streams[0]->codec->time_base.den = par.frame_rate;
AVRational fps;
fps.num = 1;
fps.den = par.frame_rate;
av_stream_set_r_frame_rate(av_fmt_ctx_out->streams[0], fps);
mp4h->av_fmt_ctx_out->streams[0]->first_dts = AV_TIME_BASE;
av_dict_set(&pMetaData, "title", par.guid_video_function, 0);
av_dict_set(&pMetaData, "artist", "Test Artist", 0);
av_dict_set(&pMetaData, "date", TSstrdate, 0);
av_fmt_ctx_out->metadata = pMetaData;
if (avformat_write_header(av_fmt_ctx_out, NULL) < 0) {
goto FnExit;
}
//............. Now for each frame_rate........
av_init_packet(&av_pkt);
if (first_frame)
{
av_pkt.pts = 0;
av_pkt.dts = 0;
}
else
{
av_pkt.pts = last_pts + (long long int)((img->timestamp_absolute - last_frame_ts_absolute) * (unsigned long long)av_stream->time_base.den / 1000000ULL);
av_pkt.dts = last_pts + (long long int)((img->timestamp_absolute - last_frame_ts_absolute) * (unsigned long long)av_stream->time_base.den / 1000000ULL);
}
mp4h->av_pkt.duration = 0;
mp4h->av_pkt.pos = -1;
last_frame_ts_utc = img->timestamp_utc.t;
last_frame_ts_absolute = img->timestamp_absolute.t;
last_pts = av_pkt.pts;
if (img->type == keyframe)
{
av_pkt.flags |= AV_PKT_FLAG_KEY;
}
av_pkt.data = img->ptr;
av_pkt.size = img->size;
av_pkt.stream_index = av_stream->index;
ret = av_interleaved_write_frame(av_fmt_ctx_out, &av_pkt);
if (ret != 0) {
char strE[256];
av_strerror(ret, strE, sizeof(strE));
trace_error("av_write_frame returns %d - %s", ret, strE);
return;
}
//........then I will close the file
FnExit:
if (av_fmt_ctx_out && av_fmt_ctx_out->pb != NULL) {
if (av_write_trailer(mp4h->av_fmt_ctx_out) != 0) {
trace_error("av_write_trailer Error!");
}
}
if (ifmt_ctx)
avformat_close_input(&ifmt_ctx);
avio_closep(&av_fmt_ctx_out->pb);
avcodec_close(av_stream->codec);
avformat_free_context(av_fmt_ctx_out);
}
How can I modify it in order to embed the actual timestamp of each frame?
I tried to add the actual timestamp to the first frame pts instead of setting it to zero, but it didn't work.

Why is my OpenSSL/libcrypto signature incorrect?

I need to sign a string, publish the public key as a string, and then somewhere else use the public key to verify the signed message. This is the part where the message is signed:
// RSA keypair generation
EVP_PKEY *keypair = NULL;
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (1 != EVP_PKEY_keygen_init(ctx)) {
initFail = true;
}
if (1 != EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048)) {
initFail = true;
}
if (1 != EVP_PKEY_keygen(ctx, &keypair)) {
initFail = true;
}
EVP_PKEY_CTX_free(ctx);
// Create public key string.
BIO* bo = BIO_new(BIO_s_mem());
PEM_write_bio_PUBKEY(bo, keypair);
char buff[1000];
BIO_read(bo, &buff[0], 1000);
BIO_free(bo);
pubkey = buff;
// Create signature
size_t *slen = new size_t;
unsigned char *sig = NULL;
std::string msg;
msg = stuffThatCreatesMessage();
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
if (1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(),
NULL, keypair)) {
initFail = true;
}
if (1 != EVP_DigestSignUpdate(mdctx, msg.c_str(), msg.length())) {
initFail = true;
}
if (1 != EVP_DigestSignFinal(mdctx, NULL, slen)) {
initFail = true;
}
sig = (unsigned char *) OPENSSL_malloc(
sizeof(unsigned char) * (*slen));
if (1 != EVP_DigestSignFinal(mdctx, sig, slen)) {
initFail = true;
}
signature = *sig;
OPENSSL_free(sig);
bool isSuccess = verifySignature(signature, pubkey, msg);
Here's the code that takes the string message and key and actually verifies the signature:
bool verifySignature(std::string sig, std::string key_str, std::string msg) {
BIO* bo = BIO_new(BIO_s_mem());
BIO_write(bo, key_str.c_str(), key_str.length());
EVP_PKEY *key = EVP_PKEY_new();
PEM_read_bio_PUBKEY(bo, &key, 0, 0);
BIO_free(bo);
unsigned char *unsigned_sig = new unsigned char[sig.length()+1];
strcpy((char *) unsigned_sig, sig.c_str());
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
if (1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, key)) {
return false;
}
if (1 != EVP_DigestVerifyUpdate(mdctx, msg.c_str(), msg.length())) {
return false;
}
bool retval = (1 == EVP_DigestVerifyFinal(mdctx, unsigned_sig,
sig.length()));
delete unsigned_sig;
return retval;
}
Every time I do this, the latter function tells me the signature is invalid, with the isSuccess variable equal to 0. It's because the EVP_DigestSignFinal is returning 0, indicating that the signature is incorrect. Where am I going wrong?
The problem, pointed out by #jww, was the line signature = *sig. I was ending up with only the first byte as my signature string. The correct way to do it is:
std::string temp_sig = reinterpret_cast<char*>(sig);
signature = temp_sig.substr(0, *slen);

Is it possible to have 2 WinSock servers on 2 different ports?

i have a quick question, i have 1 tcp proxy server wich helps me redirect data from 1 port to another, ie: 55500 to 55510, now i want to make the server to listen to another port, let`s say 55520, all this at the same time, is it possible?
I have tried examples found here to bind to another port, but maybe i am doing something wrong :(
I have tried to create a IOCP server after i startup the proxy server, but it crashes... any ideas? or maybe a example? Any help would be apreciated!
This is my proxytcp:
#include "ProxyTCP.h"
#include <process.h>
#include "GInclude.h"
using namespace std;
CProxyTCP::CProxyTCP() :
_guid(0),
_started(false),
_hevent_start(NULL),
_hevent_stop(NULL),
_serv_sock(INVALID_SOCKET),
_connect_callback(NULL),
_connect_param(NULL),
_close_callback(NULL),
_close_param(NULL),
_send_callback(NULL),
_send_param(NULL),
_recv_callback(NULL),
_recv_param(NULL)
{
InitializeCriticalSection(&_csect);
InitializeCriticalSection(&_csect_dbg);
}
CProxyTCP::~CProxyTCP()
{
Stop();
DeleteCriticalSection(&_csect);
DeleteCriticalSection(&_csect_dbg);
}
bool CProxyTCP::Start(const char *src_addr, unsigned short src_port, const char *dest_addr, unsigned short dest_port)
{
sockaddr_in addr = {};
int res;
if (_started) {
_DBG_OUTPUT("Error, server already started!");
return false;
}
RemoveAllConnInfo();
_removed_conn.clear();
_hthr_pool.clear();
if (!CreateSockAddr(src_addr, src_port, &addr)) {
_DBG_OUTPUT("Error, incorrect source address");
return false;
}
if (!dest_addr || !CreateSockAddr(dest_addr, dest_port, &_serv_addr)) {
_DBG_OUTPUT("Error, incorrect destination address");
return false;
}
_serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (_serv_sock == INVALID_SOCKET) {
_DBG_OUTPUT("Error, socket() failed with code " << WSAGetLastError());
return false;
}
res = bind(_serv_sock, (sockaddr *)&addr, sizeof(addr));
if (res == SOCKET_ERROR) {
_DBG_OUTPUT("Error, bind() failed with code " << WSAGetLastError());
closesocket(_serv_sock);
return false;
}
_hevent_start = CreateEvent(NULL, true, false, NULL);
if (!_hevent_start) {
_DBG_OUTPUT("Error, CreateEvent() failed with code " << GetLastError());
closesocket(_serv_sock);
return false;
}
_hevent_stop = CreateEvent(NULL, true, true, NULL);
if (!_hevent_start) {
_DBG_OUTPUT("Error, CreateEvent() failed with code " << GetLastError());
CloseHandle(_hevent_start);
closesocket(_serv_sock);
return false;
}
_started = true;
_beginthreadex(NULL, 0, proxy_conn_gate, this, 0, NULL);
if (WaitForSingleObject(_hevent_start, 10000) != WAIT_OBJECT_0) {
_DBG_OUTPUT("Error, WaitForSingleObject() failed");
Stop();
return false;
}
return true;
}
void CProxyTCP::Stop()
{
bool retn = false;
HANDLE *pthr_pool;
unsigned int count;
EnterCriticalSection(&_csect);
if (!_started) {
retn = true;
} else {
_started = false;
}
LeaveCriticalSection(&_csect);
if (retn) {
return;
}
if (_serv_sock != INVALID_SOCKET) {
closesocket(_serv_sock);
_serv_sock = INVALID_SOCKET;
}
WaitForSingleObject(_hevent_stop, INFINITE);
EnterCriticalSection(&_csect);
count = _hthr_pool.size() * 2;
if (count != 0) {
try {
pthr_pool = new HANDLE[count];
} catch (...) {
pthr_pool = NULL;
}
map<unsigned int, std::pair<HANDLE, HANDLE>>::iterator it = _hthr_pool.begin();
for (unsigned int i = 0; i < count; i += 2, it++) {
pthr_pool[i] = it->second.first;
pthr_pool[i + 1] = it->second.second;
}
list<PProxy_Client>::iterator it_conn = _conn.begin();
PProxy_Client pelem;
for (unsigned int i = 0; i < _conn.size(); i++, it_conn++) {
pelem = *it_conn;
closesocket(pelem->client);
closesocket(pelem->server);
}
}
LeaveCriticalSection(&_csect);
if (count == 0) {
return;
}
if (pthr_pool == NULL) {
Sleep(2000); //hmm...
} else {
WaitForMultipleObjects(count, pthr_pool, true, 2000);
}
RemoveAllConnInfo();
}
bool CProxyTCP::IsStarted()
{
return _started;
}
void CProxyTCP::RegConnectFilter(tcp_proxy_connect_filter callback, void *param)
{
_connect_callback = callback;
_connect_param = param;
}
void CProxyTCP::UnregConnectFilter()
{
_connect_callback = NULL;
_connect_param = NULL;
}
void CProxyTCP::RegCloseFilter(tcp_proxy_close_filter callback, void *param)
{
_close_callback = callback;
_close_param = param;
}
void CProxyTCP::UnregCloseFilter()
{
_close_callback = NULL;
_close_param = NULL;
}
void CProxyTCP::RegSendFilter(tcp_proxy_traffic_filter callback, void *param)
{
_send_callback = callback;
_send_param = param;
}
void CProxyTCP::UnregSendFilter()
{
_send_callback = NULL;
_send_param = NULL;
}
void CProxyTCP::RegRecvFilter(tcp_proxy_traffic_filter callback, void *param)
{
_recv_callback = callback;
_recv_param = param;
}
void CProxyTCP::UnregRecvFilter()
{
_recv_callback = NULL;
_recv_param = NULL;
}
bool CProxyTCP::CreateSockAddr(const char *addr, unsigned short port, sockaddr_in *psaddr)
{
psaddr->sin_family = AF_INET;
psaddr->sin_port = htons(port);
if (!addr) {
psaddr->sin_addr.s_addr = 0;
} else {
psaddr->sin_addr.s_addr = inet_addr(addr);
if (psaddr->sin_addr.s_addr == INADDR_NONE) {
HOSTENT *host;
host = gethostbyname(addr);
if (!host) {
return false;
}
psaddr->sin_addr.s_addr = host->h_addr[0];
}
}
return true;
}
unsigned int CProxyTCP::AddConnInfo(SOCKET client)
{
PProxy_Client pelem = new Proxy_Client;
EnterCriticalSection(&_csect);
__try {
pelem->id = GenGuid();
pelem->client = client;
pelem->server = INVALID_SOCKET;
pelem->client_init = false;
pelem->server_init = false;
pelem->started = false;
pelem->hevent_init = CreateEvent(NULL, false, false, NULL);
if (!pelem->hevent_init) {
delete pelem;
return INVALID_CONN_ID;
}
pelem->hevent_sync = CreateEvent(NULL, false, false, NULL);
if (!pelem->hevent_sync) {
CloseHandle(pelem->hevent_init);
delete pelem;
return INVALID_CONN_ID;
}
_conn.push_back(pelem);
} __finally {
LeaveCriticalSection(&_csect);
}
return pelem->id;
}
CProxyTCP::PProxy_Client CProxyTCP::GetFreeClientConnInfo()
{
list<PProxy_Client>::iterator it;
PProxy_Client pelem = NULL;
EnterCriticalSection(&_csect);
it = _conn.begin();
while (it != _conn.end()) {
if ((*it)->client_init == false) {
pelem = (*it);
pelem->client_init = true;
break;
}
it++;
}
LeaveCriticalSection(&_csect);
return pelem;
}
CProxyTCP::PProxy_Client CProxyTCP::GetFreeServerConnInfo()
{
list<PProxy_Client>::iterator it;
PProxy_Client pelem = NULL;
EnterCriticalSection(&_csect);
it = _conn.begin();
while (it != _conn.end()) {
if ((*it)->server_init == false) {
pelem = (*it);
pelem->server_init = true;
break;
}
it++;
}
LeaveCriticalSection(&_csect);
return pelem;
}
bool CProxyTCP::RemoveConnInfo(unsigned int conn_id)
{
list<PProxy_Client>::iterator it;
bool res = false;
EnterCriticalSection(&_csect);
it = _conn.begin();
while (it != _conn.end()) {
if ((*it)->id == conn_id) {
(*it)->started = false;
if ((*it)->client) {
closesocket((*it)->client);
}
if ((*it)->server) {
closesocket((*it)->server);
}
if ((*it)->hevent_sync) {
SetEvent((*it)->hevent_sync);
CloseHandle((*it)->hevent_sync);
}
if ((*it)->hevent_init) {
SetEvent((*it)->hevent_init);
CloseHandle((*it)->hevent_init);
}
_conn.erase(it);
res = true;
break;
}
it++;
}
LeaveCriticalSection(&_csect);
return res;
}
void CProxyTCP::RemoveAllConnInfo()
{
list<PProxy_Client>::iterator it;
EnterCriticalSection(&_csect);
it = _conn.begin();
while (it != _conn.end()) {
(*it)->started = false;
if ((*it)->client) {
closesocket((*it)->client);
}
if ((*it)->server) {
closesocket((*it)->server);
}
if ((*it)->hevent_sync) {
SetEvent((*it)->hevent_sync);
CloseHandle((*it)->hevent_sync);
}
if ((*it)->hevent_init) {
SetEvent((*it)->hevent_init);
CloseHandle((*it)->hevent_init);
}
it++;
}
LeaveCriticalSection(&_csect);
}
void CProxyTCP::ClearClosedResources()
{
list<unsigned int>::iterator it;
EnterCriticalSection(&_csect);
it = _removed_conn.begin();
while (it != _removed_conn.end()) {
_hthr_pool.erase(*it);
it++;
}
LeaveCriticalSection(&_csect);
}
void CProxyTCP::ConnectionCtrl()
{
SOCKET client_sock = INVALID_SOCKET;
HANDLE hthr_client, hthr_server;
sockaddr_in saddr;
unsigned int id;
int res;
ResetEvent(_hevent_stop);
SetEvent(_hevent_start);
while (_started) {
res = listen(_serv_sock, SOMAXCONN);
if (res == SOCKET_ERROR) {
_DBG_OUTPUT("Error, ConnectionCtrl::listen() failed with code " << res);
break;
}
client_sock = accept(_serv_sock, (sockaddr *)&saddr, NULL);
if (client_sock == INVALID_SOCKET) {
continue;
}
id = AddConnInfo(client_sock);
if (id == INVALID_CONN_ID) {
_DBG_OUTPUT("Error, ConnectionCtrl::AddConnInfo() failed");
continue;
}
if (_connect_callback) {
if (!_connect_callback(id, &saddr, _connect_param)) {
RemoveConnInfo(id);
closesocket(client_sock);
continue;
}
}
//SOCKADDR_IN client_info = {0};
//int addrsize = sizeof(client_info);
//getpeername(client_sock, &saddr, sizeof(saddr));
// char *ip = inet_ntoa(saddr.sin_addr);
//g_Log.LogAdd(g_Colors.Gold(), "test %s", ip);
//_DBG_OUTPUT(">>>> Client #" << id << " connected");
EnterCriticalSection(&_csect);
hthr_client = (HANDLE)_beginthreadex(NULL, 0, proxy_send_gate, this, 0, NULL);
hthr_server = (HANDLE)_beginthreadex(NULL, 0, proxy_recv_gate, this, 0, NULL);
_hthr_pool.insert(
pair<unsigned int, pair<HANDLE, HANDLE>>(
id, pair<HANDLE, HANDLE>(hthr_client, hthr_server)
)
);
LeaveCriticalSection(&_csect);
ClearClosedResources();
}
SetEvent(_hevent_stop);
}
void CProxyTCP::SendCtrl(PProxy_Client client)
{
enum { MAX_BUF_LEN = 2048 };
char recvbuf[MAX_BUF_LEN];
int res;
res = WaitForSingleObject(client->hevent_sync, 10000);
if (res != WAIT_OBJECT_0) {
_DBG_OUTPUT("Error, SendCtrl::WaitForSingleObject() failed with code " << GetLastError());
return;
}
//init
/*for(ptr = _serv_addr; ptr != NULL; ptr = ptr->ai_next) {
client->server = socket(_serv_addr->ai_family, _serv_addr->ai_socktype, _serv_addr->ai_protocol);
if (client->server == INVALID_SOCKET) {
_DBG_OUTPUT("Error, SendCtrl::socket() failed with code " << WSAGetLastError());
return;
}
res = connect(client->server, ptr->ai_addr, (int)ptr->ai_addrlen);
if (res == SOCKET_ERROR) {
closesocket(client->server);
client->server = INVALID_SOCKET;
continue;
}
break;
}
if (client->server == INVALID_SOCKET) {
return;
}*/
client->server = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (client->server == INVALID_SOCKET) {
_DBG_OUTPUT("Error, SendCtrl::socket() failed with code " << WSAGetLastError());
return;
}
res = connect(client->server, (sockaddr *)&_serv_addr, sizeof(_serv_addr));
if (res == SOCKET_ERROR) {
_DBG_OUTPUT("Error, SendCtrl::connect() failed with code " << WSAGetLastError());
closesocket(client->server);
client->server = INVALID_SOCKET;
return;
}
client->started = true;
SetEvent(client->hevent_init);
//worked cycle
while (client->started && _started) {
res = recv(client->client, recvbuf, MAX_BUF_LEN, 0);
if (res == 0) {
break;
} else if (res < 0) {
break;
}
if (_send_callback) {
res = _send_callback(client->id, recvbuf, res, MAX_BUF_LEN, _send_param);
if (res == 0) {
break;
} else if (res < 0) {
break;
}
}
res = send(client->server, recvbuf, res, 0);
if (res == SOCKET_ERROR) {
break;
}
}
client->started = false;
closesocket(client->client);
closesocket(client->server);
WaitForSingleObject(client->hevent_sync, 10000);
if (_close_callback) {
_close_callback(client->id, _close_param);
}
EnterCriticalSection(&_csect);
_removed_conn.insert(_removed_conn.begin(), client->id);
LeaveCriticalSection(&_csect);
//_DBG_OUTPUT("<<<< Client #" << client->id << " closed");
}
void CProxyTCP::RecvCtrl(PProxy_Client client)
{
enum { MAX_BUF_LEN = 2048 };
char recvbuf[MAX_BUF_LEN];
int res;
SetEvent(client->hevent_sync);
res = WaitForSingleObject(client->hevent_init, 10000);
if (res != WAIT_OBJECT_0) {
_DBG_OUTPUT("Error, RecvCtrl::WaitForSingleObject() failed with code " << GetLastError());
return;
}
//worked cycle
while (client->started && _started) {
res = recv(client->server, recvbuf, MAX_BUF_LEN, 0);
if (res == 0) {
break;
} else if (res < 0) {
break;
}
if (_recv_callback) {
res = _recv_callback(client->id, recvbuf, res, MAX_BUF_LEN, _recv_param);
if (res == 0) {
break;
} else if (res < 0) {
break;
}
}
res = send(client->client, recvbuf, res, 0);
if (res == SOCKET_ERROR) {
break;
}
}
client->started = false;
SetEvent(client->hevent_sync);
}
unsigned int __stdcall CProxyTCP::proxy_conn_gate(void *param)
{
CProxyTCP *pthis = (CProxyTCP *)param;
pthis->ConnectionCtrl();
pthis->Stop();
_endthreadex(0);
return 0;
}
unsigned int __stdcall CProxyTCP::proxy_send_gate(void *param)
{
CProxyTCP *pthis = (CProxyTCP *)param;
PProxy_Client client;
client = pthis->GetFreeServerConnInfo();
if (!client) {
_endthreadex(1);
return 1;
}
pthis->SendCtrl(client);
pthis->RemoveConnInfo(client->id);
_endthreadex(0);
return 0;
}
unsigned int __stdcall CProxyTCP::proxy_recv_gate(void *param)
{
CProxyTCP *pthis = (CProxyTCP *)param;
PProxy_Client client;
client = pthis->GetFreeClientConnInfo();
if (!client) {
_endthreadex(1);
return 1;
}
pthis->RecvCtrl(client);
_endthreadex(0);
return 0;
}

WinSock2.2 stops responding when i do disk operations

i've write a socket class in C++, the design is event-based, that means, every 64 players it will create a new thread to handle these sockets. My problem is, when i start reading a file, or write, or even copy and paste, it says "Server.exe is not responding", and when the process finish (disk), it starts responding again, disconnecting some players in my server.
Here is my listener:
void ServerSocket::ListenerThread(ServerSocket * Server)
{
// Inicializa a lista de espera.
InitializeCriticalSection(&Server->m_EventCheckers.Lock);
InitializeCriticalSection(&Server->m_Pending.Lock);
bool TerminateThread = false;
DWORD Result = 0;
WSANETWORKEVENTS NetEvents = { 0 };
// Enquanto for permitida a leitura de novas conexões.
while (WaitForSingleObject(Server->m_Listener.WaitObject, FALSE) != WAIT_OBJECT_0)
{
Result = WSAWaitForMultipleEvents(1, &Server->m_Listener.Event, FALSE, 2500, FALSE);
if (Result == WSA_WAIT_EVENT_0)
{
// Existe algo pendente no soquete.
// Enumera os eventos pendentes.
Result = WSAEnumNetworkEvents(Server->m_Listener.Socket, Server->m_Listener.Event, &NetEvents);
if (Result != SOCKET_ERROR)
{
// Verifica qual evento está ativo.
if (NetEvents.lNetworkEvents & FD_ACCEPT)
{
INT ErrorCode = NetEvents.iErrorCode[FD_ACCEPT_BIT];
if (ErrorCode == NULL)
{
// Aceita uma nova conexão.
Client* User = new Client();
if (User->AcceptFromSocket(Server->m_Listener.Socket))
{
int LastUserCount;
// Coloca na lista de espera e verifica as procedures.
EnterCriticalSection(&Server->m_Pending.Lock);
LastUserCount = Server->m_ConnectionCount++;
Server->m_Pending.Clients.push_front(User);
LastUserCount += Server->m_Pending.Clients.size();
LeaveCriticalSection(&Server->m_Pending.Lock);
EnterCriticalSection(&Server->m_EventCheckers.Lock);
if (Server->m_EventCheckers.Runnings.size() * WSA_MAXIMUM_WAIT_EVENTS < LastUserCount)
{
std::shared_ptr<ThreadInformation> Information = std::make_shared<ThreadInformation>();
Information->EventObject = CreateEventA(NULL, TRUE, FALSE, NULL);
Information->Thread.Initialize(std::thread(EventChecker, Server, Information));
Server->m_EventCheckers.Runnings.push_back(Information);
char szMessage[256] = { 0 };
sprintf_s(szMessage, "Número de Threads( %d ) -> Jogadores( %d )",
Server->m_EventCheckers.Runnings.size(), LastUserCount);
World::ServerManager->LogFile("Socket", szMessage);
}
LeaveCriticalSection(&Server->m_EventCheckers.Lock);
}
else
{
// Algum erro ocorreu durante o accept.
delete User;
}
}
else
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
}
else if (NetEvents.lNetworkEvents & FD_CLOSE)
{
INT ErrorCode = NetEvents.iErrorCode[FD_CLOSE_BIT];
if (ErrorCode == NULL)
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
else
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
}
}
else
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
}
else if (Result != WSA_WAIT_TIMEOUT)
{
// Fecha a escuta.
SetEvent(Server->m_Listener.WaitObject);
TerminateThread = true;
}
}
if (TerminateThread)
{
Server->m_Listener.WaitObject = INVALID_HANDLE_VALUE;
WSACloseEvent(Server->m_Listener.Event);
closesocket(Server->m_Listener.Socket);
Log("Function: ServerSocket::ListenerThread(). Details: TerminateThread is true.\n");
}
// Deleta a lista de espera.
DeleteCriticalSection(&Server->m_Pending.Lock);
DeleteCriticalSection(&Server->m_EventCheckers.Lock);
}
And here is where i handle the socket.
void ServerSocket::EventChecker(ServerSocket * Server, std::shared_ptr<ThreadInformation> Information)
{
SOCKET Sockets[WSA_MAXIMUM_WAIT_EVENTS] = { INVALID_SOCKET };
WSAEVENT Events[WSA_MAXIMUM_WAIT_EVENTS] = { WSA_INVALID_EVENT };
DWORD LastConnection = GetCurrentTime();
DWORD LastUserCheck = NULL;
DWORD Result = NULL;
WSANETWORKEVENTS NetworkEvents = { 0 };
std::vector<std::shared_ptr<Client>> Clients;
// Predicate to Erase-Remove Idiom.
auto UserPredicate = [&](std::shared_ptr<Client> User)
{
if (!User || User->GetSocket() == INVALID_SOCKET || User->GetEvent() == WSA_INVALID_EVENT || User->GetFreeFlag())
return true;
return false;
};
while (WaitForSingleObject(Information->EventObject, FALSE) != WAIT_OBJECT_0)
{
// Se não tiver clientes conectados, sai da thread para economizar CPU.
if (Clients.empty() && GetCurrentTime() - LastConnection > 150)
{
SetEvent(Information->EventObject);
continue;
}
// Verifica se esta na hora de pegar os usuários na lista de espera.
if (LastUserCheck + 2000 < GetCurrentTime() && Clients.size() < WSA_MAXIMUM_WAIT_EVENTS)
{
// Possui algum usuário na lista de espera.
EnterCriticalSection(&Server->m_Pending.Lock);
// Obtêm o usuário da lista.
for (size_t i = 0; i < Server->m_Pending.Clients.size(); i++)
{
if (Clients.size() < WSA_MAXIMUM_WAIT_EVENTS)
{
Client * User = Server->m_Pending.Clients.back();
if (User)
{
// Obtêm o ownership do usuário com um ponteiro compartilhado.
Clients.push_back(std::move(std::shared_ptr<Client>(User)));
Server->m_Pending.Clients.pop_back();
}
}
else
break;
}
LeaveCriticalSection(&Server->m_Pending.Lock);
LastUserCheck = GetCurrentTime();
}
// Verifica por conexões não autenticadas.
for (int i = 0; i < (int)Clients.size(); i++)
{
if (!Clients[i]->isInitialized() && !Clients[i]->GetPlayerData())
{
if (Clients[i]->GetLastRecvTime() + Connection::MaxAutorizationTime < GetCurrentTime())
{
// Percorre todos os jogadores para desconectar o IP.
for (int c = 0; c < (int)Clients.size(); c++)
{
if (_strcmpi(Clients[i]->GetIP(), Clients[c]->GetIP()) == 0)
{
Clients[c]->CloseSocket();
}
}
}
}
}
// Verifica por conexões inválidas de time-out.
for (int i = 0; i < (int)Clients.size(); i++)
{
if (Clients[i]->GetLastRecvTime() + (60 * 1000) < GetCurrentTime())
{
if (!Clients[i]->isReceivingUpdate())
{
Clients[i]->CloseSocket();
}
}
}
// Verifica por eventos inválidos ou jogadores "recém desconectados".
Clients.erase(std::remove_if(Clients.begin(), Clients.end(), UserPredicate), Clients.end());
// Separa os eventos e os soquetes.
for (unsigned i = 0; i < Clients.size(); i++)
{
Sockets[i] = Clients[i]->GetSocket();
Events[i] = Clients[i]->GetEvent();
}
// Caso não exista um usuário, apenas continua o loop.
if (Clients.empty())
continue;
LastConnection = GetCurrentTime();
Result = WSAWaitForMultipleEvents(Clients.size(), Events, FALSE, 1000, FALSE);
if (Result != SOCKET_ERROR)
{
if (Result >= WSA_WAIT_EVENT_0 && Result < WSA_MAXIMUM_WAIT_EVENTS + WSA_WAIT_EVENT_0)
{
INT Index = Result - WSA_WAIT_EVENT_0;
if (Clients.size() >= 0 && Index < int(Clients.size()))
{
std::shared_ptr<Client> & User = Clients[Index];
Result = WSAEnumNetworkEvents(User->GetSocket(), User->GetEvent(), &NetworkEvents);
if (Result != SOCKET_ERROR)
{
INT ErrorCode = 0;
if (NetworkEvents.lNetworkEvents & FD_READ)
{
ErrorCode = NetworkEvents.iErrorCode[FD_READ_BIT];
if (ErrorCode == FALSE)
{
// O soquete está com dados pendentes.
char DataReceived[Connection::MAX_BufferSize] = { 0 };
int Len = recv(User->GetSocket(), DataReceived, sizeof(DataReceived), NULL);
if (Len > 0)
{
if (User->isFirstRecv())
{
if (Len >= 4)
{
User->Initialize();
}
else
{
Clients.erase(Clients.begin() + Index);
continue;
}
}
if (!User->PushRecv(DataReceived, Len))
{
Clients.erase(Clients.begin() + Index);
continue;
}
}
else
{
Clients.erase(Clients.begin() + Index);
}
}
else
{
Log("Function: ServerSocket::RunSocketProcedure(). Details: FD_ReadBit is %d.\n", ErrorCode);
Server->AddLostConnection(Clients[Index]);
Clients.erase(Clients.begin() + Index);
continue;
}
}
else if (NetworkEvents.lNetworkEvents & FD_WRITE)
{
ErrorCode = NetworkEvents.iErrorCode[FD_WRITE_BIT];
if (ErrorCode == FALSE)
{
// O soquete está livre para mandar dados.
User->WriteData();
}
else
{
Log("Function: ServerSocket::RunSocketProcedure(). Details: FD_WriteBit is %d.\n", ErrorCode);
Server->AddLostConnection(Clients[Index]);
Clients.erase(Clients.begin() + Index);
continue;
}
}
else if (NetworkEvents.lNetworkEvents & FD_CLOSE)
{
ErrorCode = NetworkEvents.iErrorCode[FD_CLOSE_BIT];
if (ErrorCode == FALSE)
{
User->GracefulShutdown();
Clients.erase(Clients.begin() + Index);
continue;
}
else
{
Log("Function: ServerSocket::RunSocketProcedure(). Details: FD_CloseBit is %d.\n", ErrorCode);
Server->AddLostConnection(Clients[Index]);
Clients.erase(Clients.begin() + Index);
continue;
}
}
}
else
{
Log("Function: ServerSocket::RunSocketProcedure(). Details: Network ErrorCode is %d.\n", WSAGetLastError());
Server->AddLostConnection(Clients[Index]);
Clients.erase(Clients.begin() + Index);
continue;
}
}
}
}
else if (Result != WSA_WAIT_TIMEOUT)
{
char szMessage[256] = { 0 };
sprintf_s(szMessage, "WSAWaitForMultipleEvents Error Code [ %d ]", Result);
World::ServerManager->LogFile("Socket", szMessage);
Sleep(100);
}
}
EnterCriticalSection(&Server->m_EventCheckers.Lock);
Information->EventObject = INVALID_HANDLE_VALUE;
for (unsigned i = 0; i < Server->m_EventCheckers.Runnings.size(); i++)
{
if (Server->m_EventCheckers.Runnings[i] == Information)
{
Server->m_EventCheckers.Runnings.erase(Server->m_EventCheckers.Runnings.begin() + i);
break;
}
}
LeaveCriticalSection(&Server->m_EventCheckers.Lock);
}