EvEmu  0.8.4
11 September 2021
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ImageServerConnection.cpp
Go to the documentation of this file.
1 /*
2  ------------------------------------------------------------------------------------
3  LICENSE:
4  ------------------------------------------------------------------------------------
5  This file is part of EVEmu: EVE Online Server Emulator
6  Copyright 2006 - 2021 The EVEmu Team
7  For the latest information visit https://evemu.dev
8  ------------------------------------------------------------------------------------
9  This program is free software; you can redistribute it and/or modify it under
10  the terms of the GNU Lesser General Public License as published by the Free Software
11  Foundation; either version 2 of the License, or (at your option) any later
12  version.
13 
14  This program is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License along with
19  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20  Place - Suite 330, Boston, MA 02111-1307, USA, or go to
21  http://www.gnu.org/copyleft/lesser.txt.
22  ------------------------------------------------------------------------------------
23  Author: caytchen
24 */
25 
27 
28 boost::asio::const_buffers_1 ImageServerConnection::_responseOK = boost::asio::buffer("HTTP/1.0 200 OK\r\nContent-Type: image/jpeg\r\n\r\n", 45);
29 boost::asio::const_buffers_1 ImageServerConnection::_responseNotFound = boost::asio::buffer("HTTP/1.0 404 Not Found\r\n\r\n", 26);
30 boost::asio::const_buffers_1 ImageServerConnection::_responseRedirectBegin = boost::asio::buffer("HTTP/1.0 301 Moved Permanently\r\nLocation: ", 42);
31 boost::asio::const_buffers_1 ImageServerConnection::_responseRedirectEnd = boost::asio::buffer("\r\n\r\n", 4);
32 
34 : _socket(io),
35 _category(0),
36 _id(0),
37 _size(0),
38 _redirectUrl(ImageServer::FallbackURL)
39 {
40 }
41 
42 boost::asio::ip::tcp::socket& ImageServerConnection::socket()
43 {
44  return _socket;
45 }
46 
48 {
49  // receive all HTTP headers from the client
50  boost::asio::async_read_until(_socket, _buffer, "\r\n\r\n", std::bind(&ImageServerConnection::ProcessHeaders, shared_from_this()));
51 }
52 
54 {
55  std::istream stream(&_buffer);
56  std::string request;
57 
58  // every request line ends with \r\n
59  std::getline(stream, request, '\r');
60 
61  if (!starts_with(request, "GET /"))
62  {
63  NotFound();
64  return;
65  }
66  request = request.substr(5);
67 
68  bool found = false;
69  for (uint32 i = 0; i < ImageServer::CategoryCount; i++)
70  {
71  if (starts_with(request, ImageServer::Categories[i]))
72  {
73  found = true;
75  request = request.substr(strlen(ImageServer::Categories[i]));
76  break;
77  }
78  }
79  if (!found)
80  {
81  NotFound();
82  return;
83  }
84 
85  if (!starts_with(request, "/"))
86  {
87  NotFound();
88  return;
89  }
90  request = request.substr(1);
91 
92  int del = request.find_first_of('_');
93  if (del == std::string::npos)
94  {
95  NotFound();
96  return;
97  }
98 
99  // might have some extra data but atoi shouldn't care
100  std::string idStr = request.substr(0, del);
101  std::string sizeStr = request.substr(del + 1);
102  _id = atoi(idStr.c_str());
103  _size = atoi(sizeStr.c_str());
104 
105  _imageData = sImageServer.GetImage(_category, _id, _size);
106  if (!_imageData) {
107  if (IsPlayerItem(_id)) {
108  sLog.Error(" Image Server","Image for itemID %u not found.", _id);
109  NotFound();
110  return;
111  } else if (IsCharacterID(_id)) {
112  sLog.Error(" Image Server","Image for charID %u not found.", _id);
113  NotFound();
114  return;
115  }
116  Redirect();
117  return;
118  }
119 
120  // first we have to send the responseOK, then our actual result
121  boost::asio::async_write(_socket, _responseOK, boost::asio::transfer_all(), std::bind(&ImageServerConnection::SendImage, shared_from_this()));
122 }
123 
125 {
126  boost::asio::async_write(_socket, boost::asio::buffer(*_imageData, _imageData->size()), boost::asio::transfer_all(), std::bind(&ImageServerConnection::Close, shared_from_this()));
127 }
128 
130 {
131  boost::asio::async_write(_socket, _responseNotFound, boost::asio::transfer_all(), std::bind(&ImageServerConnection::Close, shared_from_this()));
132 }
133 
135 {
136  boost::asio::async_write(_socket, _responseRedirectBegin, boost::asio::transfer_all(), std::bind(&ImageServerConnection::RedirectLocation, shared_from_this()));
137 }
138 
140 {
141  sLog.Error(" Image Server"," RedirectLocation() called.");
142  std::string extension = _category == "Character" ? "jpg" : "png";
143  std::stringstream url;
144  url << ImageServer::FallbackURL << _category << "/" << _id << "_" << _size << "." << extension;
145  _redirectUrl = url.str();
146  boost::asio::async_write(_socket, boost::asio::buffer(_redirectUrl), boost::asio::transfer_all(), std::bind(&ImageServerConnection::RedirectFinalize, shared_from_this()));
147 }
148 
150 {
151  boost::asio::async_write(_socket, _responseRedirectEnd, boost::asio::transfer_all(), std::bind(&ImageServerConnection::Close, shared_from_this()));
152 }
153 
155 {
156  _socket.close();
157 }
158 
159 bool ImageServerConnection::starts_with(std::string& haystack, const char *const needle)
160 {
161  return haystack.substr(0, strlen(needle)).compare(needle) == 0;
162 }
163 
164 std::shared_ptr<ImageServerConnection> ImageServerConnection::create(boost::asio::io_context& io)
165 {
166  return std::shared_ptr<ImageServerConnection>(new ImageServerConnection(io));
167 }
static const char *const Categories[]
Definition: ImageServer.h:63
#define sImageServer
Definition: ImageServer.h:93
static const char *const FallbackURL
Definition: ImageServer.h:68
static std::shared_ptr< ImageServerConnection > create(boost::asio::io_context &io)
static boost::asio::const_buffers_1 _responseRedirectEnd
Handles distribution of character and related game images.
Definition: ImageServer.h:48
static boost::asio::const_buffers_1 _responseNotFound
#define sLog
Evaluates to a NewLog instance.
Definition: LogNew.h:250
std::shared_ptr< std::vector< char > > _imageData
boost::asio::ip::tcp::socket _socket
static boost::asio::const_buffers_1 _responseRedirectBegin
#define IsPlayerItem(itemID)
Definition: EVE_Defines.h:256
static const uint32 CategoryCount
Definition: ImageServer.h:64
static boost::asio::const_buffers_1 _responseOK
#define IsCharacterID(itemID)
Definition: EVE_Defines.h:206
unsigned __int32 uint32
Definition: eve-compat.h:50
boost::asio::ip::tcp::socket & socket()
boost::asio::streambuf _buffer
static bool starts_with(std::string &haystack, const char *const needle)
ImageServerConnection(boost::asio::io_context &io)