private static void EncodeSendFileRequestExtend(BinaryWriter wtr, object extendObj)
        {
            UdpPacketSendFileRequestExtend extend = extendObj as UdpPacketSendFileRequestExtend;

            if (extend == null)
            {
                throw new Exception("[EncodeImageExtend]未想定附加包");
            }

            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    LanFile file = extend.File;

                    bw.Write(file.Name);
                    bw.Write(file.Length);
                    bw.Write(file.IsFolder);

                    bw.Close();
                    ms.Close();

                    byte[] buf   = ms.ToArray();
                    byte[] enBuf = SecurityFactory.Encrypt(buf, extend.EncryptKey);

                    wtr.Write(enBuf.Length);
                    wtr.Write(enBuf);
                }
            }
        }
예제 #2
0
        private static UdpPacketSendFileRequestExtend ResolveSendFileRequestExtend(BinaryReader rdr, byte[] priKey)
        {
            int len = rdr.ReadInt32();

            byte[] buf = rdr.ReadBytes(len);

            byte[] deBuf = SecurityFactory.Decrypt(buf, priKey);

            using (MemoryStream ms = new MemoryStream(deBuf))
            {
                using (BinaryReader bw = new BinaryReader(ms))
                {
                    LanFile file = new LanFile();
                    file.Name     = bw.ReadString();
                    file.Length   = bw.ReadInt32();
                    file.IsFolder = bw.ReadBoolean();

                    bw.Close();
                    ms.Close();

                    UdpPacketSendFileRequestExtend extend = new UdpPacketSendFileRequestExtend();
                    extend.File = file;

                    return(extend);
                }
            }
        }
예제 #3
0
        private void _user_FileTransportProgressChanged(object sender, FileTransportEventArgs args)
        {
            TransportFile file = args.File;

            OutputLog("接收文件[" + file.File.Name + "]," + file.Progress + "%," +
                      LanFile.HumanReadbleLen(file.TransportedLength) + "/" +
                      LanFile.HumanReadbleLen(file.File.Length) + "," +
                      LanFile.HumanReadbleLen(file.TransportedSpeed) + "/s");
        }
예제 #4
0
        protected override void OnItemClicked(ItemClickedEventArgs args)
        {
            if (args.Button == MouseButtons.Left)
            {
                MessageListItem item = args.Item as MessageListItem;
                Message         m    = item.Message;
                Rectangle       rect = item.Bounds;

                foreach (DrawingObject dobj in item.DrawingObjects)
                {
                    RectangleF drawingObjRect = dobj.Offset(rect.X, rect.Y);

                    switch (dobj.Type)
                    {
                    //头像
                    case DrawingObjectType.ProfilePhoto:
                        if (drawingObjRect.Contains(args.Location))
                        {
                            UserProfileControl control = new UserProfileControl();
                            control.User = item.User;
                            control.Show(this.PointToScreen(args.Location));
                            return;
                        }
                        break;

                    case DrawingObjectType.Image:
                    case DrawingObjectType.File:
                    {
                        if (drawingObjRect.Contains(args.Location))
                        {
                            //点击了图像,显示大图, 或者打开文件
                            string path;
                            if (m.Type == MessageType.Image)
                            {
                                path = (m as ImageMessage).OriginPath;
                            }
                            else
                            {
                                path = (m as FileMessage).OriginFilePath;
                            }
                            if (LanFile.Exists(path))
                            {
                                Process.Start(path);
                            }
                        }
                        break;
                    }
                    }
                }
            }
            else if (args.Button == MouseButtons.Right)
            {
                //交给显示右键菜单
            }
        }
예제 #5
0
파일: LanUser.cs 프로젝트: prape/LanIM
        private long SendImageCore(LanUser user, Image image, string imagePath)
        {
            string path;

            if (image != null)
            {
                path = LanConfig.Instance.GetTempFileName(".png");
                image.Save(path, ImageFormat.Png);
            }
            else
            {
                path = imagePath;
            }

            long len = LanFile.GetFileLength(path);

            if (len > UdpClientEx.UDP_MAX_BUF_SIZE)
            {
                //图像文件过大的话用文件形式发送
                return(SendFile(user, path, true));
            }
            else
            {
                UdpPacket packet = new UdpPacket();
                packet.Address = user.IP;
                packet.Port    = user.Port;
                packet.ToMAC   = user.MAC;
                packet.Command = UdpPacket.CMD_SEND_IMAGE | UdpPacket.CMD_OPTION_NEED_RESPONSE;
                packet.FromMAC = this.MAC;

                UdpPacketImageExtend extend = new UdpPacketImageExtend();
                extend.EncryptKey = user.SecurityKeys.Public;
                extend.Image      = image ?? Image.FromFile(path);
                packet.Extend     = extend;

                _client.Send(packet);

                if (image != null)
                {
                    //直接发送图像的话,临时图片就删除
                    LanFile.Delete(path);
                }

                return(packet.ID);
            }
        }
예제 #6
0
        public static void SetPhoto(string key, Image img)
        {
            string fileName = Path.Combine(LanConfig.Instance.ProfilePhotoPath, key);

            _cache.Remove(key);
            LanFile.Delete(fileName);

            if (img == null)
            {
                return;
            }

            using (Bitmap bmp = new Bitmap(img.Width, img.Height))
            {
                bmp.SetResolution(img.HorizontalResolution, img.VerticalResolution);

                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.DrawImageUnscaled(img, 0, 0);
                }
                bmp.Save(fileName, ImageFormat.Jpeg);
            }
        }
예제 #7
0
        private void SendFile_Click(object sender, EventArgs e)
        {
            if (!this.SendMessageEnabled)
            {
                return;
            }
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Filter = "所有文件|*.*";
                if (ofd.ShowDialog(this) == DialogResult.OK)
                {
                    string fileName = ofd.FileName;
                    long   id       = User.SendFile(Contacter, fileName);

                    //保存发送记录
                    Store.Models.FileMessage m = new Store.Models.FileMessage();
                    m.FromUserId     = this.User.ID;
                    m.ToUserId       = this.Contacter.ID;
                    m.OriginFilePath = fileName;
                    m.FileName       = Path.GetFileName(fileName);
                    m.FileLength     = LanFile.GetFileLength(fileName);
                    m.Flag           = true; //默认成功,后面按照失败结果设定为false

                    MessageListItem item = new MessageListItem();
                    item.ID      = id;
                    item.Message = m;
                    item.User    = this.User;
                    item.State   = MessageState.Sending;

                    item.Save();

                    AddMessageItem(item, true);

                    OnSendMessage(m);
                }
            }
        }
예제 #8
0
        private void SendFileHandler(object clientobj)
        {
            LoggerFactory.Debug("begin send file");

            TcpClient     client = null;
            NetworkStream ns     = null;

            try
            {
                client = clientobj as TcpClient;
                ns     = client.GetStream();

                if (!ns.CanRead)
                {
                    //想定外
                    ns.Close();
                    client.Close();
                    OnError(Errors.NotExistTransportId, "未收到传送ID", null, null);
                    return;
                }
            }
            catch (Exception e)
            {
                OnError(Errors.NetworkError, "尝试收取传送ID失败", null, e);
                return;
            }

            LoggerFactory.Debug("get file id");
            //取得传送的文件ID
            byte[] buff = null;
            int    len  = 0;

            try
            {
                buff = new byte[this.ReceiveBufferSize];
                len  = ns.Read(buff, 0, buff.Length);
            }
            catch (Exception e)
            {
                ns.Close();
                client.Close();
                OnError(Errors.NetworkError, "尝试收取传送ID失败", null, e);
                return;
            }

            TcpPacket packet = null;

            try
            {
                IPacketResolver resolver = PacketResolverFactory.CreateResolver(buff, 0, len, this.SecurityKeys.Private);
                packet = resolver.Resolve() as TcpPacket;
            }
            catch (Exception e)
            {
                ns.Close();
                client.Close();
                OnError(Errors.ResolveError, "解密文件ID失败", null, e);
                return;
            }

            LoggerFactory.Debug("get file");
            TcpPacketRequestFileTransportExtend extend = packet.Extend as TcpPacketRequestFileTransportExtend;

            if (!_transportFileDic.TryRemove(extend.FileID, out TransportFile file))
            {
                ns.Close();
                client.Close();
                OnError(Errors.NotExistTransportId, "不存在的文件ID=" + extend.FileID, null, null);
                return;
            }

            LanFile lanFile = file.File;

            if (!File.Exists(lanFile.Path))
            {
                ns.Close();
                client.Close();
                OnError(Errors.FileOpenError, "不存在的文件:" + lanFile.Path, file, null);
                return;
            }

            LoggerFactory.Debug("open file");
            FileStream fs = null;

            try
            {
                fs = new FileStream(lanFile.Path, FileMode.Open, FileAccess.Read);
                //TODO 对于大文件用MemoryMappedFile提高速度,但是对这个类用法不是很清楚,效率也未做实验,暂时不对应
                //MemoryMappedFile f1s = MemoryMappedFile.CreateFromFile(fs, FileMode.Open, "", 1024, MemoryMappedFileAccess.Read);
                //f1s.CreateViewStream
            }
            catch (Exception e)
            {
                ns.Close();
                client.Close();
                OnError(Errors.FileOpenError, "文件打开失败", file, e);
                return;
            }

            LoggerFactory.Debug("sending file");
            try
            {
                //发送文件
                file.StartTransport();
                long lastProgressTicks = file.NowTransportTicks;

                while ((len = fs.Read(buff, 0, buff.Length)) != 0)
                {
                    ns.Write(buff, 0, len);

                    file.Transported(len);

                    if (file.TransportedLength == file.File.Length ||
                        (DateTime.Now.Ticks - lastProgressTicks) > this._progressChangeInterval)     //避免进度太频繁,500ms一次
                    {
                        OnProgressChanged(file);
                        lastProgressTicks = file.NowTransportTicks;
                    }
                }
            }
            catch (Exception e)
            {
                OnError(Errors.NetworkError, "文件传输网络错误", file, e);
            }
            finally
            {
                fs.Close();

                ns.Flush();
                ns.Close();
                client.Close();

                OnCompleted(file);
            }
            LoggerFactory.Debug("end send file");
        }
예제 #9
0
        public void Receive(TransportFile file)
        {
            TaskFactory taskFactory = new TaskFactory();

            taskFactory.StartNew(() =>
            {
                LoggerFactory.Debug("start receive file:id={0}", file.ID);
                string tmpPath = file.SavePath + "." + Path.GetRandomFileName().Replace(".", "") + ".lamim";
                FileStream fs  = null;
                try
                {
                    fs = new FileStream(tmpPath, FileMode.Create);
                }
                catch (Exception e)
                {
                    OnError(Errors.FileOpenError, "打开文件失败:" + tmpPath, file, e);
                    return;
                }
                LoggerFactory.Debug("opened file:" + tmpPath);

                LoggerFactory.Debug("try connect remote:remote={0}, port={1}", file.Remote, file.Port);
                TcpClient tcpClient = null;
                NetworkStream ns    = null;
                try
                {
                    tcpClient = new TcpClient(AddressFamily.InterNetwork)
                    {
                        ReceiveBufferSize = this.ReceiveBufferSize
                    };

                    tcpClient.Connect(file.Remote, file.Port);

                    ns = tcpClient.GetStream();
                }
                catch (Exception e)
                {
                    OnError(Errors.NetworkError, "连接失败", file, e);
                    return;
                }
                LoggerFactory.Debug("conneted remote:remote={0}, port={1}", file.Remote, file.Port);

                LoggerFactory.Debug("encode packet, request file:id={0}", file.ID);
                TcpPacket packet    = null;
                EncodeResult result = null;
                try
                {
                    //发送要接受的文件ID
                    TcpPacketRequestFileTransportExtend extend = new TcpPacketRequestFileTransportExtend
                    {
                        EncryptKey = file.PublicKey,
                        FileID     = file.ID
                    };

                    packet = new TcpPacket
                    {
                        Command = TcpPacket.CMD_REQUEST_FILE_TRANSPORT,
                        Extend  = extend
                    };

                    IPacketEncoder encoder = PacketEncoderFactory.CreateEncoder(packet);
                    result = encoder.Encode(null);
                }
                catch (Exception e)
                {
                    OnError(Errors.EncodeError, "请求文件ID包加密失败。" + packet.ToString(), file, e);
                    return;
                }

                LoggerFactory.Debug("send packet, request file:id={0}", file.ID);
                try
                {
                    ns.Write(result.Fragments[0], 0, result.Fragments[0].Length);
                }
                catch (Exception e)
                {
                    OnError(Errors.NetworkError, "请求文件ID包发送失败", file, e);
                    return;
                }

                LoggerFactory.Debug("receive file start:id={0}", file.ID);
                try
                {
                    int len = 0;
                    file.StartTransport();
                    long lastProgressTicks = file.NowTransportTicks;

                    byte[] buff = new byte[this.ReceiveBufferSize];
                    while ((len = ns.Read(buff, 0, buff.Length)) != 0)
                    {
                        fs.Write(buff, 0, len);

                        file.Transported(len);

                        if (file.TransportedLength == file.File.Length ||
                            (DateTime.Now.Ticks - lastProgressTicks) > this._progressChangeInterval) //避免进度太频繁,500ms一次
                        {
                            OnProgressChanged(file);
                            lastProgressTicks = file.NowTransportTicks;
                        }
                    }
                    LoggerFactory.Debug("receive file end:id={0}", file.ID);
                }
                catch (Exception e)
                {
                    OnError(Errors.NetworkError, "文件接收失败", file, e);
                }
                finally
                {
                    LoggerFactory.Debug("close connect and save file:id={0}", file.ID);
                    //关闭连接
                    ns.Close();
                    tcpClient.Close();

                    fs.Flush(true);
                    fs.Close();

                    if (LanFile.Rename(tmpPath, file.SavePath))
                    {
                        //发送接收完毕
                        OnCompleted(file);
                    }
                    else
                    {
                        OnError(Errors.FileWriteError, "文件写入失败", file, null);
                    }
                }
                LoggerFactory.Debug("end receive file:id={0}", file.ID);
            });
        }
예제 #10
0
        protected override void OnDrawItem(UI.DrawItemEventArgs args)
        {
            MessageListItem item = args.Item as MessageListItem;
            Message         m    = item.Message;

            args.DrawBackground();

            Graphics g = args.Graphics;

            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            Rectangle rect = item.Bounds;

            Rectangle drawingObjRect;
            Point     pos = PointToClient(MousePosition);

            foreach (DrawingObject dobj in item.DrawingObjects)
            {
                drawingObjRect = dobj.Offset(rect.X, rect.Y);

                switch (dobj.Type)
                {
                //头像
                case DrawingObjectType.ProfilePhoto:
                {
                    g.DrawImage(ProfilePhotoPool.GetPhoto(item.User.ID), drawingObjRect);

                    if (drawingObjRect.Contains(pos))
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }
                    break;
                }

                //时间, 昵称,状态
                case DrawingObjectType.Title:
                {
                    string text = item.User.NickName + "  " + m.Time.ToString("yyyy/MM/dd HH:mm:ss");
                    if (!m.Flag)
                    {
                        text += "  传送失败";
                    }
                    TextRenderer.DrawText(g, text,
                                          args.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y)
                                          , m.Flag ? SUCCESS_TITLE_COLOR : ERROR_TITLE_COLOR, TextFormatFlags.Left);
                    break;
                }

                //文本消息
                case DrawingObjectType.TextBlock:
                {
                    TextBlockObj tb       = dobj.Tag as TextBlockObj;
                    StringPart   sp       = tb.StringPart;
                    int          selStart = Math.Min(tb.SelectionStart, tb.SelectionEnd);
                    int          selEnd   = Math.Max(tb.SelectionStart, tb.SelectionEnd);

                    string str1 = selStart == -1 ? sp.String : sp.String.Substring(0, selStart);
                    string str2 = selStart == -1 ? "" : sp.String.Substring(selStart, tb.SelectionLength);
                    string str3 = selEnd == -1 ? "" : sp.String.Substring(selEnd + 1);

                    //选择前的文本
                    if (!string.IsNullOrEmpty(str1))
                    {
                        TextRenderer.DrawText(g, str1, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y), args.ForeColor,
                                              StringMeasurer.TextFormatFlags);
                    }

                    //选择中文本
                    if (!string.IsNullOrEmpty(str2))
                    {
                        int w1 = StringMeasurer.Width(g, sp.Font, str1, sp.TextFormatFlags);
                        int w2 = StringMeasurer.Width(g, sp.Font, str2, sp.TextFormatFlags);
                        drawingObjRect.X    += w1;
                        drawingObjRect.Width = w2;

                        g.FillRectangle(BrushPool.GetBrush(TEXT_SELECTION_BACK_COLOR), drawingObjRect);
                        TextRenderer.DrawText(g, str2, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y),
                                              TEXT_SELECTION_FORE_COLOR, StringMeasurer.TextFormatFlags);

                        //选择后的文本
                        if (!string.IsNullOrEmpty(str3))
                        {
                            drawingObjRect.X    += w2;
                            drawingObjRect.Width = dobj.Width - w1 - w2;
                            TextRenderer.DrawText(g, str3, sp.Font, new Point((int)drawingObjRect.X, (int)drawingObjRect.Y), args.ForeColor,
                                                  StringMeasurer.TextFormatFlags);
                        }
                    }
                    break;
                }

                case DrawingObjectType.Image:
                {
                    Image image = (m as ImageMessage).Image;
                    g.DrawImage(image, drawingObjRect);

                    if (drawingObjRect.Contains(pos))
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }
                    else
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }
                    break;
                }

                case DrawingObjectType.File:
                {
                    FileMessage fm = m as FileMessage;

                    //底背景
                    g.FillRectangle(Brushes.White, drawingObjRect);
                    if (drawingObjRect.Contains(pos))
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN_FOCUS, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }
                    else
                    {
                        g.DrawRectangle(IMAGE_BORDER_PEN, drawingObjRect.X, drawingObjRect.Y, drawingObjRect.Width, drawingObjRect.Height);
                    }

                    //文件名,文件大小,ICON
                    Image image       = FileIconPool.GetIcon(fm.OriginFilePath);
                    int   imageWidth  = 64;
                    int   imageHeight = 64 * image.Height / image.Width;

                    Rectangle imageRect    = new Rectangle(drawingObjRect.X + FILE_SEND_WIDTH - imageWidth - MARGIN, drawingObjRect.Y + MARGIN, imageWidth, FILE_SEND_HEIGHT - Font.Height - MARGIN * 3);
                    Rectangle fileNameRect = new Rectangle(drawingObjRect.X + MARGIN, drawingObjRect.Y + MARGIN, FILE_SEND_WIDTH - imageWidth - MARGIN * 3, FILE_SEND_HEIGHT - Font.Height - MARGIN * 3);
                    Rectangle fontRect     = new Rectangle(drawingObjRect.X + MARGIN, drawingObjRect.Y + FILE_SEND_HEIGHT - Font.Height - MARGIN, FILE_SEND_WIDTH - MARGIN * 2, Font.Height);
                    Rectangle pieRect      = new Rectangle(drawingObjRect.X + (FILE_SEND_WIDTH - PROGRESS_PIE_D) / 2, drawingObjRect.Y + (FILE_SEND_HEIGHT - PROGRESS_PIE_D) / 2, PROGRESS_PIE_D, PROGRESS_PIE_D);
                    Rectangle processRect  = new Rectangle(drawingObjRect.X, drawingObjRect.Y + (FILE_SEND_HEIGHT - Font.Height * 2) / 2, FILE_SEND_WIDTH, Font.Height * 2);

                    //当文件名超过显示部分时,中间用省略号表示
                    string str = fm.FileName;
                    SizeF  s   = g.MeasureString(fm.FileName, Font, new System.Drawing.SizeF((float)fileNameRect.Width, (float)fileNameRect.Height), StringFormat.GenericDefault, out int count, out int lines);
                    if (s.Height >= fileNameRect.Height & str.Length >= count)
                    {
                        //由于会出现半行的情况,直接写死了所取的字符串数目
                        str = str.Substring(0, 36) + "・・・" + str.Substring(str.Length - 4);
                    }
                    g.DrawImage(image, imageRect.X, imageRect.Y, imageWidth, imageHeight);
                    g.DrawString(str, args.Font, Brushes.Black, fileNameRect);
                    TextRenderer.DrawText(g, LanFile.HumanReadbleLen(fm.FileLength), args.Font, fontRect, Color.FromArgb(0, 0, 0), TextFormatFlags.Left);

                    if (item.State == MessageState.Receiving ||
                        item.State == MessageState.Sending)
                    {
                        //接受进度
                        g.FillRectangle(MESSAGELIST_PROGRESS_BACKGROUND_BRUSH, drawingObjRect);

                        g.DrawPie(PROGRESS_PEN, pieRect, 0, 360);
                        g.FillPie(MESSAGELIST_PROGRESS_FILLED_BRUSH, pieRect, 0, 360 * item.Progress / 100);

                        //TODO 显示剩余时间,传输速度
                        TextRenderer.DrawText(g, item.Progress + "%" + "\r\n" + LanFile.HumanReadbleLen(item.FileTransportedLength) + "/" + LanFile.HumanReadbleLen(fm.FileLength),
                                              args.Font, processRect, Color.FromArgb(0, 0, 0), TextFormatFlags.HorizontalCenter);
                    }
                    break;
                }
                }
            }
        }