1 /* 2 * Copyright 2002-2007, Marcus Overhagen. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <OS.h> 7 #include <Messenger.h> 8 #include <string.h> 9 #include <unistd.h> 10 #include "debug.h" 11 #include "PortPool.h" 12 #include "MediaMisc.h" 13 #include "DataExchange.h" 14 #include "ServerInterface.h" 15 16 #define TIMEOUT 15000000 // 15 seconds timeout! 17 18 namespace BPrivate { 19 namespace media { 20 21 team_id team; 22 23 namespace dataexchange { 24 25 BMessenger *MediaServerMessenger; 26 static port_id MediaServerPort; 27 static port_id MediaAddonServerPort; 28 29 void find_media_server_port(); 30 void find_media_addon_server_port(); 31 32 static BMessenger * GetMediaServerMessenger() { 33 static BMessenger * messenger = new BMessenger(B_MEDIA_SERVER_SIGNATURE); 34 return MediaServerMessenger = messenger; 35 } 36 37 class initit 38 { 39 public: 40 initit() 41 { 42 MediaServerMessenger = 0; 43 find_media_server_port(); 44 find_media_addon_server_port(); 45 46 thread_info info; 47 get_thread_info(find_thread(NULL), &info); 48 team = info.team; 49 } 50 ~initit() 51 { 52 delete MediaServerMessenger; 53 } 54 }; 55 initit _initit; 56 57 58 void find_media_server_port() 59 { 60 MediaServerPort = find_port(MEDIA_SERVER_PORT_NAME); 61 if (MediaServerPort < 0) { 62 ERROR("couldn't find MediaServerPort\n"); 63 MediaServerPort = BAD_MEDIA_SERVER_PORT; // make this a unique number 64 } 65 } 66 67 void find_media_addon_server_port() 68 { 69 MediaAddonServerPort = find_port(MEDIA_ADDON_SERVER_PORT_NAME); 70 if (MediaAddonServerPort < 0) { 71 ERROR("couldn't find MediaAddonServerPort\n"); 72 MediaAddonServerPort = BAD_MEDIA_ADDON_SERVER_PORT; // make this a unique number 73 } 74 } 75 76 77 status_t 78 request_data::SendReply(status_t result, reply_data *reply, int replysize) const 79 { 80 reply->result = result; 81 // we cheat and use the (command_data *) version of SendToPort 82 return SendToPort(reply_port, 0, reinterpret_cast<command_data *>(reply), replysize); 83 } 84 85 86 // BMessage based data exchange with the media_server 87 status_t SendToServer(BMessage *msg) 88 { 89 status_t rv; 90 rv = GetMediaServerMessenger()->SendMessage(msg, static_cast<BHandler *>(NULL), TIMEOUT); 91 if (rv != B_OK) { 92 ERROR("SendToServer: SendMessage failed, error 0x%08lx (%s)\n", rv, strerror(rv)); 93 DEBUG_ONLY(msg->PrintToStream()); 94 } 95 return rv; 96 } 97 98 99 status_t 100 QueryServer(BMessage &request, BMessage &reply) 101 { 102 status_t status = GetMediaServerMessenger()->SendMessage(&request, &reply, TIMEOUT, TIMEOUT); 103 if (status != B_OK) { 104 ERROR("QueryServer: SendMessage failed, error 0x%08lx (%s)\n", status, strerror(status)); 105 DEBUG_ONLY(request.PrintToStream()); 106 DEBUG_ONLY(reply.PrintToStream()); 107 } 108 return status; 109 } 110 111 112 // Raw data based data exchange with the media_server 113 status_t SendToServer(int32 msgcode, command_data *msg, int size) 114 { 115 return SendToPort(MediaServerPort, msgcode, msg, size); 116 } 117 118 status_t QueryServer(int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) 119 { 120 return QueryPort(MediaServerPort, msgcode, request, requestsize, reply, replysize); 121 } 122 123 124 // Raw data based data exchange with the media_addon_server 125 status_t SendToAddonServer(int32 msgcode, command_data *msg, int size) 126 { 127 return SendToPort(MediaAddonServerPort, msgcode, msg, size); 128 } 129 130 131 status_t QueryAddonServer(int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) 132 { 133 return QueryPort(MediaAddonServerPort, msgcode, request, requestsize, reply, replysize); 134 } 135 136 137 // Raw data based data exchange with the media_server 138 status_t SendToPort(port_id sendport, int32 msgcode, command_data *msg, int size) 139 { 140 status_t rv; 141 142 rv = write_port_etc(sendport, msgcode, msg, size, B_RELATIVE_TIMEOUT, TIMEOUT); 143 if (rv != B_OK) { 144 ERROR("SendToPort: write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, sendport, rv, strerror(rv)); 145 if (rv == B_BAD_PORT_ID && sendport == MediaServerPort) { 146 find_media_server_port(); 147 sendport = MediaServerPort; 148 } else if (rv == B_BAD_PORT_ID && sendport == MediaAddonServerPort) { 149 find_media_addon_server_port(); 150 sendport = MediaAddonServerPort; 151 } else { 152 return rv; 153 } 154 155 rv = write_port_etc(sendport, msgcode, msg, size, B_RELATIVE_TIMEOUT, TIMEOUT); 156 if (rv != B_OK) { 157 ERROR("SendToPort: retrying write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, sendport, rv, strerror(rv)); 158 return rv; 159 } 160 } 161 return B_OK; 162 } 163 164 165 status_t QueryPort(port_id requestport, int32 msgcode, request_data *request, int requestsize, reply_data *reply, int replysize) 166 { 167 status_t rv; 168 int32 code; 169 170 request->reply_port = _PortPool->GetPort(); 171 172 rv = write_port_etc(requestport, msgcode, request, requestsize, B_RELATIVE_TIMEOUT, TIMEOUT); 173 174 if (rv != B_OK) { 175 ERROR("QueryPort: write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, requestport, rv, strerror(rv)); 176 if (rv == B_BAD_PORT_ID && requestport == MediaServerPort) { 177 find_media_server_port(); 178 requestport = MediaServerPort; 179 } else if (rv == B_BAD_PORT_ID && requestport == MediaAddonServerPort) { 180 find_media_addon_server_port(); 181 requestport = MediaAddonServerPort; 182 } else { 183 _PortPool->PutPort(request->reply_port); 184 return rv; 185 } 186 187 rv = write_port_etc(requestport, msgcode, request, requestsize, B_RELATIVE_TIMEOUT, TIMEOUT); 188 if (rv != B_OK) { 189 ERROR("QueryPort: retrying write_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, requestport, rv, strerror(rv)); 190 _PortPool->PutPort(request->reply_port); 191 return rv; 192 } 193 } 194 195 rv = read_port_etc(request->reply_port, &code, reply, replysize, B_RELATIVE_TIMEOUT, TIMEOUT); 196 _PortPool->PutPort(request->reply_port); 197 198 if (rv < B_OK) { 199 ERROR("QueryPort: read_port failed, msgcode 0x%lx, port %ld, error %#lx (%s)\n", msgcode, request->reply_port, rv, strerror(rv)); 200 } 201 202 return (rv < B_OK) ? rv : reply->result; 203 } 204 205 }; // dataexchange 206 }; // media 207 }; // BPrivate 208 209