⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fileshare.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
📖 第 1 页 / 共 3 页
字号:
  *path = pathname.pathname();}bool FileShareSession::GetItemBaseUrl(size_t index, bool preview,                                      std::string* url) {  // This function composes a URL to the referenced item.  It may be a local  // file url (file:///...), or a remote peer url relayed through localhost  // (http://...)  ASSERT(NULL != url);  if (index >= manifest_->size()) {    ASSERT(false);    return false;  }  const FileShareManifest::Item& item = manifest_->item(index);  bool is_remote;  if (is_sender_) {    if (!preview) {      talk_base::Pathname path(local_folder_);      path.SetFilename(item.name);      *url = path.url();      return true;    }    is_remote = false;  } else {    if ((index < stored_location_.size()) && !stored_location_[index].empty()) {      if (!preview) {        *url = talk_base::Pathname(stored_location_[index]).url();        return true;      }      // Note: Using the local downloaded files as a source for previews is      // desireable, because it means that previews can be regenerated if IE's      // cached versions get flushed for some reason, and the remote side is      // not available.  However, it has the downside that IE _must_ regenerate      // the preview locally, which takes time, memory and CPU.  Eventually,      // we will unify the remote and local cached copy through some sort of      // smart http proxying.  In the meantime, always use the remote url, to      // eliminate the annoying transition from remote to local caching.      //is_remote = false;      is_remote = true;    } else {      is_remote = true;    }  }  talk_base::SocketAddress address;  if (!GetProxyAddress(address, is_remote))    return false;  std::string path;  GetItemNetworkPath(index, preview, &path);  talk_base::Url<char> make_url(path.c_str(),                                address.IPAsString().c_str(),                                 address.port());  *url = make_url.url();  return true;}bool FileShareSession::GetProxyAddress(talk_base::SocketAddress& address,                                       bool is_remote) {  talk_base::AsyncSocket*& proxy_listener =    is_remote ? remote_listener_ : local_listener_;  if (!proxy_listener) {    talk_base::AsyncSocket* listener =      talk_base::Thread::Current()->socketserver()                                  ->CreateAsyncSocket(SOCK_STREAM);    if (!listener)      return false;    talk_base::SocketAddress bind_address("127.0.0.1", 0);    if ((listener->Bind(bind_address) != 0)        || (listener->Listen(5) != 0)) {      delete listener;      return false;    }    LOG(LS_INFO) << "Proxy listener available @ "                 << listener->GetLocalAddress().ToString();    listener->SignalReadEvent.connect(this, &FileShareSession::OnProxyAccept);    proxy_listener = listener;  }  if (proxy_listener->GetState() == talk_base::Socket::CS_CLOSED) {    if (is_remote) {      address = remote_listener_address_;      return true;    }    return false;  }  address = proxy_listener->GetLocalAddress();  return !address.IsAny();}talk_base::StreamInterface* FileShareSession::CreateChannel(    const std::string& channel_name) {  ASSERT(NULL != session_);  // Send a heads-up for our new channel  cricket::Session::XmlElements els;  buzz::XmlElement* xel_channel = new buzz::XmlElement(QN_SHARE_CHANNEL, true);  xel_channel->AddAttr(buzz::QN_NAME, channel_name);  els.push_back(xel_channel);  session_->SendInfoMessage(els);  cricket::PseudoTcpChannel* channel =    new cricket::PseudoTcpChannel(talk_base::Thread::Current(), session_);  VERIFY(channel->Connect(channel_name));  return channel->GetStream();}void FileShareSession::SetState(FileShareState state, bool prevent_close) {  if (state == state_)    return;  if (IsComplete()) {    // Entering a completion state is permanent.    ASSERT(false);    return;  }  state_ = state;  if (IsComplete()) {    // All completion states auto-close except for FS_COMPLETE    bool close = (state_ > FS_COMPLETE) || !prevent_close;    if (close) {      DoClose(true);    }  }  SignalState(state_);}void FileShareSession::OnInitiate() {  // Cache the variables we will need, in case session_ goes away  is_sender_ = session_->initiator();  jid_ = buzz::Jid(session_->remote_name());  manifest_ = new FileShareManifest(description()->manifest);  source_path_ = description()->source_path;  preview_path_ = description()->preview_path;  if (local_folder_.empty()) {    LOG(LS_ERROR) << "FileShareSession - no local folder, using temp";    talk_base::Pathname temp_folder;    talk_base::Filesystem::GetTemporaryFolder(temp_folder, true, NULL);    local_folder_ = temp_folder.pathname();  }  LOG(LS_INFO) << session_->state();  SetState(FS_OFFER, false);}void FileShareSession::NextDownload() {  if (FS_TRANSFER != state_)    return;  if (item_transferring_ >= manifest_->size()) {    // Notify the other side that transfer has completed    cricket::Session::XmlElements els;    els.push_back(new buzz::XmlElement(QN_SHARE_COMPLETE, true));    session_->SendInfoMessage(els);    SetState(FS_COMPLETE, !proxies_.empty());    return;  }  const FileShareManifest::Item& item = manifest_->item(item_transferring_);  if ((item.type != FileShareManifest::T_FILE)      && (item.type != FileShareManifest::T_IMAGE)      && (item.type != FileShareManifest::T_FOLDER)) {    item_transferring_ += 1;    NextDownload();    return;  }  const bool is_folder = (item.type == FileShareManifest::T_FOLDER);  talk_base::Pathname temp_name;  temp_name.SetFilename(item.name);  if (!talk_base::CreateUniqueFile(temp_name, !is_folder)) {    SetState(FS_FAILURE, false);    return;  }  talk_base::StreamInterface* stream = NULL;  if (is_folder) {    // Convert unique filename into unique foldername    temp_name.AppendFolder(temp_name.filename());    temp_name.SetFilename("");    talk_base::TarStream* tar = new talk_base::TarStream;    // Note: the 'target' directory will be a subdirectory of the transfer_path_    talk_base::Pathname target;    target.SetFolder(item.name);    tar->AddFilter(target.pathname());    if (!tar->Open(temp_name.pathname(), false)) {      delete tar;      SetState(FS_FAILURE, false);      return;    }    stream = tar;    tar->SignalNextEntry.connect(this, &FileShareSession::OnNextEntry);  } else {    talk_base::FileStream* file = new talk_base::FileStream;    if (!file->Open(temp_name.pathname().c_str(), "wb")) {      delete file;      talk_base::Filesystem::DeleteFile(temp_name);      SetState(FS_FAILURE, false);      return;    }    stream = file;  }  ASSERT(NULL != stream);  transfer_path_ = temp_name.pathname();  std::string remote_path;  GetItemNetworkPath(item_transferring_, false, &remote_path);  StreamCounter* counter = new StreamCounter(stream);  counter->SignalUpdateByteCount.connect(this, &FileShareSession::OnUpdateBytes);  counter_ = counter;  http_client_->reset();  http_client_->set_server(talk_base::SocketAddress(jid_.Str(), 0, false));  http_client_->request().verb = talk_base::HV_GET;  http_client_->request().path = remote_path;  http_client_->response().document.reset(counter);  http_client_->start();}const FileShareSession::FileShareDescription* FileShareSession::description()const {  ASSERT(NULL != session_);  const cricket::SessionDescription* desc =    session_->initiator() ? session_->description()                          : session_->remote_description();  return static_cast<const FileShareDescription*>(desc);}void FileShareSession::DoClose(bool terminate) {  ASSERT(!is_closed_);  ASSERT(IsComplete());  ASSERT(NULL != session_);  is_closed_ = true;  if (http_client_) {    http_client_->reset();  }  if (http_server_) {    http_server_->CloseAll(true);    // Currently, CloseAll doesn't result in OnHttpRequestComplete callback.    // If we change that, the following resetting won't be necessary.    transfer_connection_id_ = talk_base::HTTP_INVALID_CONNECTION_ID;    transfer_name_.clear();    counter_ = NULL;  }  // 'reset' and 'CloseAll' cause counter_ to clear.  ASSERT(NULL == counter_);  if (remote_listener_) {    // Cache the address for the remote_listener_, so that we can continue to    // present a consistent URL for remote previews, which is necessary for IE    // to continue using its cached copy.    remote_listener_address_ = remote_listener_->GetLocalAddress();    remote_listener_->Close();    LOG(LS_INFO) << "Proxy listener closed @ "                 << remote_listener_address_.ToString();  }  if (terminate) {    session_->Terminate();  }}///////////////////////////////// FileShareSessionClient //////////////////////////////void FileShareSessionClient::OnSessionCreate(cricket::Session* session,                                      bool received_initiate) {  VERIFY(sessions_.insert(session).second);  if (received_initiate) {    FileShareSession* share = new FileShareSession(session, user_agent_);    SignalFileShareSessionCreate(share);    UNUSED(share);  // FileShareSession registers itself with the UI  }}void FileShareSessionClient::OnSessionDestroy(cricket::Session* session) {  VERIFY(1 == sessions_.erase(session));}const cricket::SessionDescription* FileShareSessionClient::CreateSessionDescription(    const buzz::XmlElement* element) {  FileShareSession::FileShareDescription* share_desc =    new FileShareSession::FileShareDescription;  if (element->Name() != QN_SHARE_DESCRIPTION)    return share_desc;  const buzz::XmlElement* manifest = element->FirstNamed(QN_SHARE_MANIFEST);  const buzz::XmlElement* protocol = element->FirstNamed(QN_SHARE_PROTOCOL);  if (!manifest || !protocol)    return share_desc;  for (const buzz::XmlElement* item = manifest->FirstElement();       item != NULL; item = item->NextElement()) {    bool is_folder;    if (item->Name() == QN_SHARE_FOLDER) {      is_folder = true;    } else if (item->Name() == QN_SHARE_FILE) {      is_folder = false;    } else {      continue;    }    std::string name;    if (const buzz::XmlElement* el_name = item->FirstNamed(QN_SHARE_NAME)) {      name = el_name->BodyText();    }    if (name.empty()) {      continue;    }    size_t size = FileShareManifest::SIZE_UNKNOWN;    if (item->HasAttr(QN_SIZE)) {      size = strtoul(item->Attr(QN_SIZE).c_str(), NULL, 10);    }    if (is_folder) {      share_desc->manifest.AddFolder(name, size);    } else {      // Check if there is a valid image description for this file.      if (const buzz::XmlElement* image = item->FirstNamed(QN_SHARE_IMAGE)) {        if (image->HasAttr(QN_WIDTH) && image->HasAttr(QN_HEIGHT)) {          size_t width = strtoul(image->Attr(QN_WIDTH).c_str(), NULL, 10);          size_t height = strtoul(image->Attr(QN_HEIGHT).c_str(), NULL, 10);          if (AllowedImageDimensions(width, height)) {            share_desc->manifest.AddImage(name, size, width, height);            continue;          }        }      }      share_desc->manifest.AddFile(name, size);    }  }  if (const buzz::XmlElement* http = protocol->FirstNamed(QN_SHARE_HTTP)) {    share_desc->supports_http = true;    for (const buzz::XmlElement* url = http->FirstNamed(QN_SHARE_URL);         url != NULL; url = url->NextNamed(QN_SHARE_URL)) {      if (url->Attr(buzz::QN_NAME) == kHttpSourcePath) {        share_desc->source_path = url->BodyText();      } else if (url->Attr(buzz::QN_NAME) == kHttpPreviewPath) {        share_desc->preview_path = url->BodyText();      }    }  }  return share_desc;}buzz::XmlElement* FileShareSessionClient::TranslateSessionDescription(    const cricket::SessionDescription* description) {  const FileShareSession::FileShareDescription* share_desc =    static_cast<const FileShareSession::FileShareDescription*>(description);  scoped_ptr<buzz::XmlElement> el(new buzz::XmlElement(QN_SHARE_DESCRIPTION,                                                       true));  const FileShareManifest& manifest = share_desc->manifest;  el->AddElement(new buzz::XmlElement(QN_SHARE_MANIFEST));  for (size_t i=0; i<manifest.size(); ++i) {    const FileShareManifest::Item& item = manifest.item(i);    buzz::QName qname;    if (item.type == FileShareManifest::T_FOLDER) {      qname = QN_SHARE_FOLDER;    } else if ((item.type == FileShareManifest::T_FILE)               || (item.type == FileShareManifest::T_IMAGE)) {      qname = QN_SHARE_FILE;    } else {      ASSERT(false);      continue;    }    el->AddElement(new buzz::XmlElement(qname), 1);    if (item.size != FileShareManifest::SIZE_UNKNOWN) {      char buffer[256];      talk_base::sprintfn(buffer, sizeof(buffer), "%lu", item.size);      el->AddAttr(QN_SIZE, buffer, 2);    }    buzz::XmlElement* el_name = new buzz::XmlElement(QN_SHARE_NAME);    el_name->SetBodyText(item.name);    el->AddElement(el_name, 2);    if ((item.type == FileShareManifest::T_IMAGE)        && AllowedImageDimensions(item.width, item.height)) {      el->AddElement(new buzz::XmlElement(QN_SHARE_IMAGE), 2);      char buffer[256];      talk_base::sprintfn(buffer, sizeof(buffer), "%lu", item.width);      el->AddAttr(QN_WIDTH, buffer, 3);      talk_base::sprintfn(buffer, sizeof(buffer), "%lu", item.height);      el->AddAttr(QN_HEIGHT, buffer, 3);    }  }  el->AddElement(new buzz::XmlElement(QN_SHARE_PROTOCOL));  if (share_desc->supports_http) {    el->AddElement(new buzz::XmlElement(QN_SHARE_HTTP), 1);    if (!share_desc->source_path.empty()) {      buzz::XmlElement* url = new buzz::XmlElement(QN_SHARE_URL);      url->SetAttr(buzz::QN_NAME, kHttpSourcePath);      url->SetBodyText(share_desc->source_path);      el->AddElement(url, 2);    }    if (!share_desc->preview_path.empty()) {      buzz::XmlElement* url = new buzz::XmlElement(QN_SHARE_URL);      url->SetAttr(buzz::QN_NAME, kHttpPreviewPath);      url->SetBodyText(share_desc->preview_path);      el->AddElement(url, 2);    }  }  return el.release();}FileShareSession *FileShareSessionClient::CreateFileShareSession() {  cricket::Session* session = sm_->CreateSession(jid_.Str(),						 NS_GOOGLE_SHARE);  FileShareSession* share = new FileShareSession(session, user_agent_);  SignalFileShareSessionCreate(share);  return share;}} // namespace cricket

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -