#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#define SECURITY_WIN32
#include <security.h>
#include <schannel.h>
#include <shlwapi.h>
#include <assert.h>
#include <stdio.h>
#include <iostream>
#pragma comment (lib, "ws2_32.lib")
#pragma comment (lib, "secur32.lib")
#pragma comment (lib, "shlwapi.lib")
#define TLS_MAX_PACKET_SIZE (16384+512) // payload + extra over head for header/mac/padding (probably an overestimate)
typedef struct {
SOCKET sock;
CredHandle handle;
CtxtHandle context;
SecPkgContext_StreamSizes sizes;
int received; // byte count in incoming buffer (ciphertext)
int used; // byte count used from incoming buffer to decrypt current packet
int available; // byte count available for decrypted bytes
char* decrypted; // points to incoming buffer where data is decrypted inplace
char incoming[TLS_MAX_PACKET_SIZE];
} tls_socket;
int main() {
const char* hostname = "api.openai.com";
//const char* hostname = "badssl.com";
//const char* hostname = "expired.badssl.com";
//const char* hostname = "wrong.host.badssl.com";
//const char* hostname = "self-signed.badssl.com";
//const char* hostname = "untrusted-root.badssl.com";
const char* path = "/";
tls_socket s;
// initialize windows sockets
WSADATA wsadata;
if (WSAStartup(MAKEWORD(2, 2), &wsadata) != 0) {
return -1;
}
// create TCP IPv4 socket
s.sock = socket(AF_INET, SOCK_STREAM, 0);
if (s.sock == INVALID_SOCKET) {
WSACleanup();
return -1;
}
char sport[64];
wnsprintfA(sport, sizeof(sport), "%u", 443);
// connect to server
if (!WSAConnectByNameA(s.sock, hostname, sport, NULL, NULL, NULL, NULL, NULL, NULL))
{
closesocket(s.sock);
WSACleanup();
return -7;
}
// initialize schannel
{
SCHANNEL_CRED cred {};
cred
.dwVersion = SCHANNEL_CRED_VERSION;
cred .dwFlags = SCH_USE_STRONG_CRYPTO // use only strong crypto alogorithms
| SCH_CRED_AUTO_CRED_VALIDATION // automatically validate server certificate
| SCH_CRED_NO_DEFAULT_CREDS; // no client certificate authentication
cred.grbitEnabledProtocols = SP_PROT_TLS1_2; // allow only TLS v1.2
if (AcquireCredentialsHandleA(NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &s.handle, NULL) != SEC_E_OK)
{
closesocket(s.sock);
WSACleanup();
return -1;
}
}
s.received = s.used = s.available = 0;
s.decrypted = NULL;
// perform tls handshake
// 1) call InitializeSecurityContext to create/update schannel context
// 2) when it returns SEC_E_OK - tls handshake completed
// 3) when it returns SEC_I_INCOMPLETE_CREDENTIALS - server requests client certificate (not supported here)
// 4) when it returns SEC_I_CONTINUE_NEEDED - send token to server and read data
// 5) when it returns SEC_E_INCOMPLETE_MESSAGE - need to read more data from server
// 6) otherwise read data from server and go to step 1
CtxtHandle* context = NULL;
int result = 0;
for (;;) {
SecBuffer inbuffers[2] = { 0 };
inbuffers[0].BufferType = SECBUFFER_TOKEN;
inbuffers[0].pvBuffer = s.incoming;
inbuffers[0].cbBuffer = s.received;
inbuffers[1].BufferType = SECBUFFER_EMPTY;
SecBuffer outbuffers[1] = { 0 };
outbuffers[0].BufferType = SECBUFFER_TOKEN;
SecBufferDesc indesc = { SECBUFFER_VERSION, ARRAYSIZE(inbuffers), inbuffers };
SecBufferDesc outdesc = { SECBUFFER_VERSION, ARRAYSIZE(outbuffers), outbuffers };
DWORD flags = ISC_REQ_USE_SUPPLIED_CREDS | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_STREAM;
SECURITY_STATUS sec = InitializeSecurityContextA(
&s.handle,
context,
context ? NULL : (SEC_CHAR*)hostname,
flags,
0,
0,
context ? &indesc : NULL,
0,
context ? NULL : &s.context,
&outdesc,
&flags,
NULL);
if (sec == SEC_E_INVALID_TOKEN) std::cout << "failed\n";
}
}
This is the code I'm running, from https://gist.github.com/mmozeiko/c0dfcc8fec527a90a02145d2cc0bfb6d here. The error code in question is "SEC_E_INVALID_TOKEN" The same error does persist with or without the full code. It only happens on some requests, to some sites. Sending the same request several times, sometimes it has this error, other times it doesn't, and only on this site that I've found so far. What does it mean, and how can I fix it? I don't know what "token" is being referred to, because I don't even see where anything called a token is passed.
Related
This question already has answers here:
What is the effect of extern "C" in C++?
(17 answers)
C/C++ Warning: address of temporary with BDADDR_ANY Bluetooth library
(3 answers)
Closed 4 years ago.
This is the code that is working fine when compiling in C:
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
sdp_session_t *register_service(uint8_t rfcomm_channel) {
uint32_t svc_uuid_int[] = { 0x01110000, 0x00100000, 0x80000080, 0xFB349B5F };
const char *service_name = "Armatus Bluetooth server";
const char *svc_dsc = "A HERMIT server that interfaces with the Armatus Android app";
const char *service_prov = "Armatus";
uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid,
svc_class_uuid;
sdp_list_t *l2cap_list = 0,
*rfcomm_list = 0,
*root_list = 0,
*proto_list = 0,
*access_proto_list = 0,
*svc_class_list = 0,
*profile_list = 0;
sdp_data_t *channel = 0;
sdp_profile_desc_t profile;
sdp_record_t record = { 0 };
sdp_session_t *session = 0;
// set the general service ID
sdp_uuid128_create(&svc_uuid, &svc_uuid_int);
sdp_set_service_id(&record, svc_uuid);
char str[256] = "";
sdp_uuid2strn(&svc_uuid, str, 256);
printf("Registering UUID %s\n", str);
// set the service class
sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID);
svc_class_list = sdp_list_append(0, &svc_class_uuid);
sdp_set_service_classes(&record, svc_class_list);
// set the Bluetooth profile information
sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
profile.version = 0x0100;
profile_list = sdp_list_append(0, &profile);
sdp_set_profile_descs(&record, profile_list);
// make the service record publicly browsable
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root_list = sdp_list_append(0, &root_uuid);
sdp_set_browse_groups(&record, root_list);
// set l2cap information
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
l2cap_list = sdp_list_append(0, &l2cap_uuid);
proto_list = sdp_list_append(0, l2cap_list);
// register the RFCOMM channel for RFCOMM sockets
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
sdp_list_append(rfcomm_list, channel);
sdp_list_append(proto_list, rfcomm_list);
access_proto_list = sdp_list_append(0, proto_list);
sdp_set_access_protos(&record, access_proto_list);
// set the name, provider, and description
sdp_set_info_attr(&record, service_name, service_prov, svc_dsc);
// connect to the local SDP server, register the service record,
// and disconnect
session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
sdp_record_register(session, &record, 0);
// cleanup
sdp_data_free(channel);
sdp_list_free(l2cap_list, 0);
sdp_list_free(rfcomm_list, 0);
sdp_list_free(root_list, 0);
sdp_list_free(access_proto_list, 0);
sdp_list_free(svc_class_list, 0);
sdp_list_free(profile_list, 0);
return session;
}
int init_server() {
int port = 3, result, sock, client, bytes_read, bytes_sent;
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buffer[1024] = { 0 };
socklen_t opt = sizeof(rem_addr);
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) port;
// register service
sdp_session_t *session = register_service(port);
// allocate socket
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
printf("socket() returned %d\n", sock);
// bind socket to port 3 of the first available
result = bind(sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
printf("bind() on channel %d returned %d\n", port, result);
// put socket into listening mode
result = listen(sock, 1);
printf("listen() returned %d\n", result);
//sdpRegisterL2cap(port);
// accept one connection
printf("calling accept()\n");
client = accept(sock, (struct sockaddr *)&rem_addr, &opt);
printf("accept() returned %d\n", client);
ba2str(&rem_addr.rc_bdaddr, buffer);
fprintf(stderr, "accepted connection from %s\n", buffer);
memset(buffer, 0, sizeof(buffer));
return client;
}
int main(){
return init_server();
}
But when I copy this code in C++ like this:
#include <iostream>
extern "C"{
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include <bluetooth/rfcomm.h>
uint32_t svc_uuid_int[] = { 0x01110000, 0x00100000, 0x80000080, 0xFB349B5F };
const char *service_name = "Armatus Bluetooth server";
const char *svc_dsc = "A HERMIT server that interfaces with the Armatus Android app";
const char *service_prov = "Armatus";
uuid_t root_uuid, l2cap_uuid, rfcomm_uuid, svc_uuid,
svc_class_uuid;
sdp_list_t *l2cap_list = 0,
*rfcomm_list = 0,
*root_list = 0,
*proto_list = 0,
*access_proto_list = 0,
*svc_class_list = 0,
*profile_list = 0;
sdp_data_t *channel = 0;
sdp_profile_desc_t profile;
sdp_record_t record = { 0 };
sdp_session_t *session = 0;
// set the general service ID
sdp_uuid128_create(&svc_uuid, &svc_uuid_int);
sdp_set_service_id(&record, svc_uuid);
char str[256] = "";
sdp_uuid2strn(&svc_uuid, str, 256);
printf("Registering UUID %s\n", str);
// set the service class
sdp_uuid16_create(&svc_class_uuid, SERIAL_PORT_SVCLASS_ID);
svc_class_list = sdp_list_append(0, &svc_class_uuid);
sdp_set_service_classes(&record, svc_class_list);
// set the Bluetooth profile information
sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
profile.version = 0x0100;
profile_list = sdp_list_append(0, &profile);
sdp_set_profile_descs(&record, profile_list);
// make the service record publicly browsable
sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
root_list = sdp_list_append(0, &root_uuid);
sdp_set_browse_groups(&record, root_list);
// set l2cap information
sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID);
l2cap_list = sdp_list_append(0, &l2cap_uuid);
proto_list = sdp_list_append(0, l2cap_list);
// register the RFCOMM channel for RFCOMM sockets
sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID);
channel = sdp_data_alloc(SDP_UINT8, &rfcomm_channel);
rfcomm_list = sdp_list_append(0, &rfcomm_uuid);
sdp_list_append(rfcomm_list, channel);
sdp_list_append(proto_list, rfcomm_list);
access_proto_list = sdp_list_append(0, proto_list);
sdp_set_access_protos(&record, access_proto_list);
// set the name, provider, and description
sdp_set_info_attr(&record, service_name, service_prov, svc_dsc);
// connect to the local SDP server, register the service record,
// and disconnect
session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
sdp_record_register(session, &record, 0);
// cleanup
sdp_data_free(channel);
sdp_list_free(l2cap_list, 0);
sdp_list_free(rfcomm_list, 0);
sdp_list_free(root_list, 0);
sdp_list_free(access_proto_list, 0);
sdp_list_free(svc_class_list, 0);
sdp_list_free(profile_list, 0);
return session;
}
int init_server() {
int port = 3, result, sock, client, bytes_read, bytes_sent;
struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
char buffer[1024] = { 0 };
socklen_t opt = sizeof(rem_addr);
// local bluetooth adapter
loc_addr.rc_family = AF_BLUETOOTH;
loc_addr.rc_bdaddr = *BDADDR_ANY;
loc_addr.rc_channel = (uint8_t) port;
// register service
sdp_session_t *session = register_service(port);
// allocate socket
sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
printf("socket() returned %d\n", sock);
// bind socket to port 3 of the first available
result = bind(sock, (struct sockaddr *)&loc_addr, sizeof(loc_addr));
printf("bind() on channel %d returned %d\n", port, result);
// put socket into listening mode
result = listen(sock, 1);
printf("listen() returned %d\n", result);
//sdpRegisterL2cap(port);
// accept one connection
printf("calling accept()\n");
client = accept(sock, (struct sockaddr *)&rem_addr, &opt);
printf("accept() returned %d\n", client);
ba2str(&rem_addr.rc_bdaddr, buffer);
fprintf(stderr, "accepted connection from %s\n", buffer);
memset(buffer, 0, sizeof(buffer));
return client;
}
}
int main()
{
init_server();
}
It gives the following compile time error:
In file included from test.cpp:9:0:
test.cpp: In function ‘sdp_session_t* register_service(uint8_t)’:
test.cpp:115:27: error:taking address of temporary [-fpermissive]
session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
^ test.cpp:115:39: error: taking address of temporary [-fpermissive]
session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
^ test.cpp: In function ‘int init_server()’: test.cpp:138:27: error: taking address of temporary
[-fpermissive]
loc_addr.rc_bdaddr = *BDADDR_ANY;
What can I do?? Please help.
I have an IOCP based client for which I wanted to implement HTTP redirects in a following way:
1) When encountering a redirect to a different host call DisconnectEx with TF_REUSE_SOCKET
2) Await the overlapped completion and then call ConnectEx
However my code gets a WSAEISCONN return code upon calling ConnectEx even though if I check GetLastError() when the overlapped result of DisconnectEx is returned it gives 0.
An MVCE would be quite big in this case, but if there are no experience based suggestions I'll post one.
Update
I tried to make a MVCE but encountered different symptoms:
#define VC_EXTRALEAN
#define WIN32_LEAN_AND_MEAN
#include <WinSock2.h>
#include <MSWSock.h>
#include <Windows.h>
#include <Ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
#include <stdexcept>
#include <iostream>
#include <sstream>
#include <map>
static inline std::string ErrorMessage(const char* pErrorMessage, ...)
{
std::string sFormattedMessage;
va_list VariableArgumentList;
va_start(VariableArgumentList, pErrorMessage);
sFormattedMessage.resize(_vscprintf(pErrorMessage, VariableArgumentList) + 1);
vsnprintf_s(const_cast<char*>(sFormattedMessage.c_str()), sFormattedMessage.size(), sFormattedMessage.size(), pErrorMessage, VariableArgumentList);
va_end(VariableArgumentList);
return sFormattedMessage;
}
#define CHECK(x, format, ...) { if ((x) == false) throw std::runtime_error(ErrorMessage("%s(%d): "format, __FILE__, __LINE__, __VA_ARGS__)); }
template<typename T>
bool LoadWinsockExtensionFunction(SOCKET Socket, GUID Guid, T* pFunction)
{
DWORD nBytesReturned = 0;
return WSAIoctl(Socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &Guid, sizeof(Guid), pFunction, sizeof(T), &nBytesReturned, NULL, NULL) == 0 && nBytesReturned == sizeof(T);
}
int main(int argc, char** argv)
{
try
{
WORD nRequestedWinsockVersion = MAKEWORD(2, 2);
WSADATA WsaData;
CHECK(WSAStartup(nRequestedWinsockVersion, &WsaData) == 0, "WSAStartup failed");
auto hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
CHECK(hCompletionPort != NULL, "CreateIoCompletionPort failed(%d)", GetLastError());
auto Socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
CHECK(Socket != INVALID_SOCKET, "WSASocket failed(%d)", WSAGetLastError());
CHECK(CreateIoCompletionPort(reinterpret_cast<HANDLE>(Socket), hCompletionPort, NULL, 0), "CreateIoCompletionPort failed(%d)", GetLastError());
sockaddr_in LocalAddress;
ZeroMemory(&LocalAddress, sizeof(LocalAddress));
LocalAddress.sin_family = AF_INET;
LocalAddress.sin_addr.s_addr = INADDR_ANY;
LocalAddress.sin_port = 0;
CHECK(bind(Socket, reinterpret_cast<SOCKADDR*>(&LocalAddress), sizeof(LocalAddress)) == 0, "bind failed(%d)", WSAGetLastError());
LPFN_CONNECTEX pConnectEx = nullptr;
CHECK(LoadWinsockExtensionFunction(Socket, WSAID_CONNECTEX, &pConnectEx), "WSAIoctl failed to load ConnectEx(%d)", WSAGetLastError());
LPFN_DISCONNECTEX pDisconnectEx = nullptr;
CHECK(LoadWinsockExtensionFunction(Socket, WSAID_DISCONNECTEX, &pDisconnectEx), "WSAIoctl failed to load DisconnectEx(%d)", WSAGetLastError());
addrinfo Hint;
ZeroMemory(&Hint, sizeof(Hint));
Hint.ai_family = AF_INET;
Hint.ai_protocol = IPPROTO_TCP;
Hint.ai_socktype = SOCK_STREAM;
std::map<std::string, PADDRINFOA> Hosts;
// Scenarios:
// one host - failure to connect on the second try to the first host with 52
// two distinct hosts - failure to connect on the second try to the first host with 52
Hosts.emplace("www.google.com", nullptr);
Hosts.emplace("www.facebook.com", nullptr);
for (auto& Host : Hosts)
{
auto nGetAddressInfoResult = getaddrinfo(Host.first.c_str(), "http", &Hint, &Host.second);
CHECK(nGetAddressInfoResult == 0 && &Host.second, "getaddrinfo failed(%d)", nGetAddressInfoResult);
}
auto Host = Hosts.begin();
WSAOVERLAPPED Overlapped;
ZeroMemory(&Overlapped, sizeof(Overlapped));
while (true)
{
if ((*pConnectEx)(Socket, Host->second->ai_addr, Host->second->ai_addrlen, nullptr, 0, nullptr, &Overlapped) == FALSE)
{
auto nWSAError = WSAGetLastError();
CHECK(nWSAError == ERROR_IO_PENDING, "ConnectEx failed(%d)", nWSAError);
DWORD nBytesTransferred = 0;
ULONG_PTR pCompletionKey = 0;
LPOVERLAPPED pOverlapped = nullptr;
CHECK(GetQueuedCompletionStatus(hCompletionPort, &nBytesTransferred, &pCompletionKey, &pOverlapped, INFINITE), "overlapped operation failed(%d)", GetLastError());
}
CHECK(setsockopt(Socket, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0) == 0, "setsockopt failed(%d)", WSAGetLastError());
CHECK(shutdown(Socket, SD_BOTH) == 0, "shutdown failed(%d)", WSAGetLastError());
if ((*pDisconnectEx)(Socket, &Overlapped, TF_REUSE_SOCKET, 0) == FALSE)
{
auto nWSAError = WSAGetLastError();
CHECK(nWSAError == ERROR_IO_PENDING, "ConnectEx failed(%d)", nWSAError);
DWORD nBytesTransferred = 0;
ULONG_PTR pCompletionKey = 0;
LPOVERLAPPED pOverlapped = nullptr;
CHECK(GetQueuedCompletionStatus(hCompletionPort, &nBytesTransferred, &pCompletionKey, &pOverlapped, INFINITE), "overlapped operation failed(%d)", GetLastError());
}
if (++Host == Hosts.end())
{
Host = Hosts.begin();
}
}
closesocket(Socket);
CloseHandle(hCompletionPort);
for (auto& Host : Hosts)
{
freeaddrinfo(Host.second);
}
WSACleanup();
}
catch (std::exception& Exception)
{
OutputDebugStringA(Exception.what());
std::cout << Exception.what();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
With this snippet what happens is that I get ERROR_DUP_NAME on the second attempt to connect to the same host (TIME_WAIT possibly?). I assume that if I could rebind the socket (but I can't since a second bind call fails with WSAEINVAL which is correct since the socket is already bound) this could even work fine.
What I have in my original code is a redirect from localhost to the actual address of the interface - maybe there simply is a path which in that case gives out WSAEISCONN instead of ERROR_DUP_NAME ? I can't post an MVCE for the original code since then another piece of code that would accept the connections is needed (maybe I'll make one).
I actually found that if DisconnectEx is called by the client then yes, ERROR_DUP_NAME happens because of TIME_WAIT (see this for a detailed analysis). So the bottom line is I should simply not try to reuse sockets in this scenario.
I am sending values of two variables using POST to the PHP server. The C++ application using Wininet connects to the server side script, but instead of sending the data correctly, it just shows empty fields in the parameters send using POST.
#include <windows.h> #include <wininet.h> #include <stdio.h> #include <fstream> #include <cstring>
#pragma comment (lib, "Wininet.lib")
#define SIZE 128
int main() {
HINTERNET Initialize, Connection, File;
DWORD dwBytes;
static const char *postData = "name=Jack+Din&age=38";
LPSTR accept1[2] = { "Accept: */*", NULL };
const char * const frmdata = "name=Arun+Pushkar&age=38";
static const char *hdrs[] = { "Content-Type: application/x-www-form-urlencoded" };
static const char *accept[] = { "*/*", NULL };
char ch;
Initialize = InternetOpen(L"HTTPGET", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if (!Initialize)
{
printf("Failed to open session\n");
exit(0);
}
Connection = InternetConnect(Initialize, L"192.168.1.10", INTERNET_DEFAULT_HTTP_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
File = HttpOpenRequest(
Connection,
L"POST",
L"/trydata.php",
L"HTTP/1.0",
NULL,
NULL,
INTERNET_FLAG_NO_CACHE_WRITE,
0);
unsigned long dataLen = strlen((char*)frmdata)+1;
bool res = HttpSendRequest(
File, // file to which reply will come
(LPCWSTR)hdrs,
0,
(char*)frmdata, // post variables to be send
dataLen); // length of data send
if (res)
{
std::ofstream webSource;
webSource.open("a.html");
while (InternetReadFile(File, &ch, 1, &dwBytes))
{
if (dwBytes != 1)break;
webSource << ch;
}
webSource.close();
}
InternetCloseHandle(File);
InternetCloseHandle(Connection);
InternetCloseHandle(Initialize);
return 0;
}
The server side script is
<?php
$yourname = isset($_POST['name']) ? $_POST['name'] : 'no name';
$yourage = isset($_POST['age']) ? $_POST['age'] : 'no age';
echo "Hello".htmlspecialchars($yourname). "!";
echo "Your Age".htmlspecialchars($yourage). "!";
?>
When I run this C++ code I get the following in my a.html:
Hello no Name!Your Age no Age!
I would use ATL Server classes to do the same. Here is the example:
CAtlHttpClient client;
AtlNavigateData navData;
LPCSTR lpData = "data=toto";
navData.SetMethod(ATL_HTTP_METHOD_POST);
navData.SetPostData((BYTE*)lpData, lstrlenA(lpData), _T("application/x-www-form-urlencoded"));
client.Navigate(_T("mysite.net"), _T("myscript.php"), &navData);
const char* pszBody = (const char*)client.GetBody();
I'm trying to create a Bluetooth Server to run on Windows in my computer. I have been reading information in several pages and following some tutorials, but I'm getting an error creating the Bluetooth sockect.
This is the code I have at the moment.
#include "stdafx.h"
#include <WinSock2.h>
#include <ws2bth.h>
#include <bthsdpdef.h>
#include <BluetoothAPIs.h>
#pragma comment(lib, "Ws2_32.lib")
#include <new>
using namespace std;
//Some defines
#define CXN_SUCCESS 0
#define CXN_ERROR 1
void PrintError(char* ProblemMessage, int ErrorCode);
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
{
printf("Ha habido un error con wsaData\n");
}
ULONG ulRetCode = CXN_SUCCESS;
LPCSADDR_INFO lpCSAddrInfo = NULL;
TCHAR szThisComputerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwLenComputerName = MAX_COMPUTERNAME_LENGTH + 1;
SOCKET s;
lpCSAddrInfo = (LPCSADDR_INFO) HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(CSADDR_INFO) );
if ( NULL == lpCSAddrInfo ) {
wprintf(L"!ERROR! | Unable to allocate memory for CSADDR_INFO\n");
ulRetCode = CXN_ERROR;
}
if ( CXN_SUCCESS == ulRetCode ) {
if ( !GetComputerName(szThisComputerName, &dwLenComputerName) ) {
wprintf(L"=CRITICAL= | GetComputerName() call failed. WSAGetLastError=[%d]\n", WSAGetLastError());
ulRetCode = CXN_ERROR;
}
}
//
// Open a bluetooth socket using RFCOMM protocol
//
if ( CXN_SUCCESS == ulRetCode ) {
//(AF_INET, SOCK_STREAM, IPPROTO_TCP);
s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
if (s == INVALID_SOCKET)
{
PrintError("Problem found creating the socket \n",GetLastError());
printf("Error code: %d\n",GetLastError());
exit(1);
}
}
closesocket(s);
WSACleanup();
}
void PrintError(char* ProblemMessage, int ErrorCode)
{
const char* ConnectionString = ": ";
char* CompleteMessage;
LPVOID ReasonMessage;
DWORD ReasonMessageSize;
ReasonMessageSize = FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &ReasonMessage, 0, NULL);
CompleteMessage = new(nothrow) char[lstrlen(ProblemMessage) + lstrlen(ConnectionString) + ReasonMessageSize + 1];
if(!CompleteMessage)
return;
lstrcpy(CompleteMessage, ProblemMessage);
lstrcat(CompleteMessage, ConnectionString);
lstrcat(CompleteMessage, (char*)ReasonMessage);
LocalFree(ReasonMessage);
fprintf(stderr, CompleteMessage);
delete[] CompleteMessage;
}
When I lauch this code, I get the error code 10047: Address family not supported by protocol family. In the line:
s = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
What am I doing wrong? I filled the fields like it's said here:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa362910%28v=vs.85%29.aspx
And the rest of the code is based on the sample given in:
http://code.msdn.microsoft.com/windowsdesktop/Bluetooth-Connection-e3263296
Some other information that may be relevant, I'm using:
Windows 7
Microsoft Visual Studio 2010
My computer do accept Bluetooth, actually I connect it to a wireless
printer oftenly
Can anyone tell me what am I missing or what am I doing wrong?
Thanks
I have a quick question. I set this client up as a sort of example, so I do not do a lot of extra work with it; I wanted to get the basic idea working first. I have it working so far, with one exception:
If I start it up, I can see the data being sent across on the other side (I use python+twisted). I can write with no problems, the problem comes when I read. On the server side, I am able to see the text coming in and being sent back out again. But on the client side, things are delayed. I have to send three commands to see something coming out.
for example:
I send hello <newline> cruel <newline> world<newline> and get hello echoed back to me, only after I hit enter on world.
Could someone point out why or give me some hints?
Here is the code.
#include <openssl/ssl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <fcntl.h>
#include <cstdio>
//used for printing an error and then exiting.
inline void error(const char* message)
{
fprintf(stderr, "%s\n", message);
exit(EXIT_FAILURE);
}
//the buffer size we will be working with:
#define MAX_BUFF 4096
int main()
{
int ret; //used for holding bytes read.
int flag = 1; //our IOCTL flag.
char buff[MAX_BUFF]; //a buffer for holding i/o data.
fd_set rdesc, wdesc, srset, swset; //file descriptor sets.
timeval tv; //used for holding the time select should wait.
SSL_CTX* context = NULL; //ssl context.
SSL* ssl = NULL; //main ssl object.
sockaddr_in addr; //server socket address.
int sock = 0;
//clean out the struct:
bzero(&addr, sizeof(sockaddr_in));
//then fill it in.
addr.sin_family = AF_INET;
addr.sin_port = htons(4000);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr.s_addr);
//create the socket
sock=socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
error("Error creating initial socket.");
}
//initialize SSL.
SSL_load_error_strings();
SSL_library_init();
//create the ssl context
context = SSL_CTX_new(TLSv1_client_method());
if (!context)
{
error("Could not create SSL context.");
}
//connect the socket to the server.
if (connect(sock, (sockaddr*)&addr, sizeof(sockaddr_in)) < 0)
{
error("Could not connect to specified socket.");
}
//create the ssl object.
ssl = SSL_new(context);
if (!ssl)
{
error("Could not create ssl object.");
}
//try to set the socket as the fd for the ssl object.
if (!SSL_set_fd(ssl, sock))
{
error("Error, could not bind fd to the ssl object.");
}
//link ssl up with the socket.
if (!SSL_connect(ssl))
{
error("Could not perform ssl handshake.");
}
ioctl(sock, FIONBIO, &flag);
//set our file descriptor sets.
FD_SET(fileno(stdin), &wdesc);
FD_SET(sock, &rdesc);
//wait for data, read, then print.
while (1)
{
//we need to zero out our i/o buffer.
bzero(buff, MAX_BUFF);
//initialize our temp fd sets.
srset = rdesc;
swset = wdesc;
//each time select finishes it changes this to how much time it actually slept, so we need to reset it.
tv.tv_usec = 50*1000; //50 ms
tv.tv_sec = 0;
//perform the actual select operation.
select(sock+1, &srset, &swset, NULL, &tv);
//check to see if data was written on stdin (user input)
if (FD_ISSET(fileno(stdin), &swset))
{
//read inputted data.
ret = read(fileno(stdin), buff, MAX_BUFF);
if (ret)
{
//write it to the socket.
SSL_write(ssl, buff, ret);
}
}
//check to see if we received anything.
if (FD_ISSET(sock, &srset))
{
printf("in if.\n");
//read it
ret = SSL_read(ssl, buff, MAX_BUFF);
printf("%d\n", ret);
if (ret)
{
//write it to screen.
printf("%s\n", buff);
}
}
}
return 0;
}