|
Advanced Services - SMS Connectivity CPP on Windows (BSD) Sample application using HTTP to send a picture message |
![]() |
The following sample application written in CPP on Windows (BSD) sends a picture message to a single mobile telephone. The application uses HTTP to communicate with HSL's systems. To send to more than one mobile telephone at a time, separate each mobile number in the destaddr field by a comma (e.g. "447968000111,447720000111,3378100100").
#include <cstring>
#include <cstdio>
#include <windows.h>
#include <wincrypt.h>
#include <winsock2.h>
char* compute_md5_hash(const char* input);
void init_winsock(void);
int main(int argc, char* argv[]) {
// These variables fill out the various parts described in the
// interface specification
const char* host = "194.247.82.150";
const int port = 80;
const char* action = "sendnok";
const char* client_id = "<your client_id>";
const char* destaddr = "<some fully-qualified MSISDN>";
const char* type = "pg";
const char* content = "50340a232043726561746564206279205061696e74205368" \
"6f702050726f20370a37322032380a0000000000000000000003ffffffffffffff00000" \
"000000000000000e0000000000000000338000000000000000cee00000000000000131b" \
"01f81f8fe7c0006c06c0600618630000f001e0600630230000e000e0600630030000e00" \
"0e0600618030000e000e060061c030000e000e060060f030000e000e07ffe07830000e0" \
"00e0600601c30000e000e0600600e30000e000e0600600730000e000e0600600730000e" \
"000e0600620730080f001e0600630e301807c07c1f81fbf87ff801f1f00000000000000" \
"0ffe0000000000000003f80000000000000000e00000000000000000000000000000000" \
"00003ffffffffffffff000000000000000000";
const char* text = "this is a test message";
const char* url_encoded_text = "this+is+a+test+message";
const char* secret = "<your secret>";
// Compute the hash
int length = strlen(secret) + strlen(type) + strlen(content) + strlen(text)
+ 5 + strlen(destaddr) + 1;
char* accumulator = new char[length];
sprintf(accumulator,
"%s%s%s%s00000%s",
secret,
type,
content,
text,
destaddr);
char* hash = compute_md5_hash( accumulator );
// Create the URL
int buffer_size = strlen(action) + strlen(client_id) + strlen(destaddr)
+ strlen(type) + strlen(content) + strlen(url_encoded_text)
+ strlen(hash) + 80;
const char* pattern = "GET /%s/?client_id=%s&destaddr=%s&type=%s" \
"&content=%s&text=%s&key=%s HTTP/1.0\r\n\r\n";
char* buffer = new char[buffer_size];
sprintf(buffer,
pattern,
action,
client_id,
destaddr,
type,
content,
url_encoded_text,
hash);
// Clean up
delete[] hash;
// Create the socket
init_winsock();
// Create the socket
int the_socket = socket(AF_INET, SOCK_STREAM, 0);
// Set up the address
struct sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(port);
unsigned long inet_address = inet_addr(host);
memcpy( &(address.sin_addr), &inet_address, 4 );
memset( &(address.sin_zero), '\0', 8 ); // zero the rest of the struct
// Connect
connect(the_socket, (struct sockaddr *)&address, sizeof(address));
// Variables used for IO
int bytes_to_io = strlen(buffer);
int total_bytes_iod = 0;
int bytes_iod = 0;
// Send the request
while(total_bytes_iod < bytes_to_io
&& (bytes_iod = send(the_socket,
buffer + total_bytes_iod,
bytes_to_io - total_bytes_iod,
0)) != SOCKET_ERROR)
{
total_bytes_iod += bytes_iod;
}
// Read the response
buffer_size = 4096;
buffer = new char[buffer_size];
bytes_to_io = buffer_size;
total_bytes_iod = 0;
while(total_bytes_iod < buffer_size
&& (bytes_iod = recv(the_socket,
buffer + total_bytes_iod,
buffer_size - total_bytes_iod,
0)) > 0)
{
total_bytes_iod += bytes_iod;
}
buffer[total_bytes_iod] = '\0';
// Inform the user of the outcome
fprintf(stdout, "HTTP response:\n%s\n", buffer);
closesocket(the_socket);
// Clean up winsock
WSACleanup();
delete[] buffer;
return EXIT_SUCCESS;
}
/*
* This method computes the MD5 hash of the secret, text and destination
* address. It should be clear how this can be extended to other hash
* algorithms and arbitrary data.
*/
char* compute_md5_hash(const char* input)
{
// Variables used during the hashing process
HCRYPTPROV cryptoProvider;
HCRYPTHASH rawHash;
// Get the cryptographic provider for MD5 hashing
// NOTE: This call could (potentially) fail and this should be checked for
CryptAcquireContext(&cryptoProvider,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT);
// Create an object that will perform the hash
// NOTE: This call could (potentially) fail and this should be checked for
CryptCreateHash(cryptoProvider,
CALG_MD5,
0,
0,
&rawHash);
// Feed data into the hash
// NOTE: This call could (potentially) fail and this should be checked for
CryptHashData(rawHash, (unsigned char*)input, strlen(input), 0);
// Extract the hash data
// NOTE: This call could (potentially) fail and this should be checked for
DWORD hashLength = 16; //(MD5 length)
unsigned char* hashData = new unsigned char[hashLength];
CryptGetHashParam(rawHash, HP_HASHVAL, hashData, &hashLength, 0);
// Create a hex-encoded string of the hash bytes
char lut[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
char* hash = new char[33];
for(int i = 0; i < 16; i++) {
hash[2 * i] = lut[(hashData[i] & 0xF0) >> 4];
hash[2 * i + 1] = lut[hashData[i] & 0x0F];
}
hash[32] = '\0';
// After processing, cryptoProvider and hasher must be released.
if(rawHash) {
CryptDestroyHash(rawHash);
}
if(cryptoProvider) {
CryptReleaseContext(cryptoProvider, 0);
}
delete[] hashData;
return hash;
}
void init_winsock(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup( wVersionRequested, &wsaData );
if(err != 0) {
fprintf(stderr, "no winsock was found\n");
exit(EXIT_FAILURE);
}
/* Check that the Winsock version installed is of a high-enough version. */
if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
WSACleanup();
fprintf(stderr, "no suitable winsock was available\n");
exit(EXIT_FAILURE);
}
}
picture_message_http.cpp
Copyright © Hay Systems Ltd 2004
Owner: support@haysystems.com 20 September 2004